Skip to Content.
Sympa Menu

perfsonar-dev - [pS-dev] [GEANT/SA2/ps-java-services] r6492 - in trunk: perfsonar-web-admin-0/src/main/java/perfSONARW ebAdmin/admin/service perfsonar-web-admin-0/src/main/java/ perfSONARWebAdmin/auxiliary/service perfsonar-web-admin-0/ src/main/webapp/graphics perfsonar_base/src/main/java/or g/perfsonar/service/measurementArchive/metadataConfig perf sonar_base/src/main/java/org/perfsonar/service/measureme ntArchive/metadataConfig/queryGenerator

Subject: perfsonar development work

List archive

[pS-dev] [GEANT/SA2/ps-java-services] r6492 - in trunk: perfsonar-web-admin-0/src/main/java/perfSONARW ebAdmin/admin/service perfsonar-web-admin-0/src/main/java/ perfSONARWebAdmin/auxiliary/service perfsonar-web-admin-0/ src/main/webapp/graphics perfsonar_base/src/main/java/or g/perfsonar/service/measurementArchive/metadataConfig perf sonar_base/src/main/java/org/perfsonar/service/measureme ntArchive/metadataConfig/queryGenerator


Chronological Thread 
  • From:
  • To:
  • Subject: [pS-dev] [GEANT/SA2/ps-java-services] r6492 - in trunk: perfsonar-web-admin-0/src/main/java/perfSONARW ebAdmin/admin/service perfsonar-web-admin-0/src/main/java/ perfSONARWebAdmin/auxiliary/service perfsonar-web-admin-0/ src/main/webapp/graphics perfsonar_base/src/main/java/or g/perfsonar/service/measurementArchive/metadataConfig perf sonar_base/src/main/java/org/perfsonar/service/measureme ntArchive/metadataConfig/queryGenerator
  • Date: Mon, 10 Feb 2014 15:36:39 +0000 (GMT)

Author: dante.delvaux
Date: 2014-02-10 15:36:39 +0000 (Mon, 10 Feb 2014)
New Revision: 6492

Removed:
trunk/perfsonar-web-admin-0/src/main/webapp/graphics/Paul_Hasleham.vcf
trunk/perfsonar-web-admin-0/src/main/webapp/graphics/Thumbs.db
Modified:

trunk/perfsonar-web-admin-0/src/main/java/perfSONARWebAdmin/admin/service/Admin.java

trunk/perfsonar-web-admin-0/src/main/java/perfSONARWebAdmin/auxiliary/service/HTMLOutput.java

trunk/perfsonar_base/src/main/java/org/perfsonar/service/measurementArchive/metadataConfig/MetadataConfigurationStorageManager.java

trunk/perfsonar_base/src/main/java/org/perfsonar/service/measurementArchive/metadataConfig/Transformations.java

trunk/perfsonar_base/src/main/java/org/perfsonar/service/measurementArchive/metadataConfig/queryGenerator/IperfQueryGenerator.java
Log:
pSbase1: adding a bit of debug logging
web-admin-0: making code a bit more readable

Modified:
trunk/perfsonar-web-admin-0/src/main/java/perfSONARWebAdmin/admin/service/Admin.java
===================================================================
---
trunk/perfsonar-web-admin-0/src/main/java/perfSONARWebAdmin/admin/service/Admin.java
2014-02-10 13:55:12 UTC (rev 6491)
+++
trunk/perfsonar-web-admin-0/src/main/java/perfSONARWebAdmin/admin/service/Admin.java
2014-02-10 15:36:39 UTC (rev 6492)
@@ -164,10 +164,8 @@
servicePath = sc.getRealPath("/");
PerfsonarProperties properties;
// Loading the servlet properties
- ServletProperties servletProperties = new
ServletPropertiesImpl(
- servicePath + ServletPropertiesPath);
- String extra = servletProperties.getProperties().getProperty(
- "servlet.extra_functionalities");
+ ServletProperties servletProperties = new
ServletPropertiesImpl(servicePath + ServletPropertiesPath);
+ String extra =
servletProperties.getProperties().getProperty("servlet.extra_functionalities");

log4jProperties = getLog4jProperty();
if( log4jProperties == null ) return;
@@ -188,9 +186,7 @@
output.setOuputStream(out);

if (session.getAttribute("propertyType") != null) {
-
- if (session.getAttribute("propertyType")
- .equals("loggingProperties")) {
+ if
(session.getAttribute("propertyType").equals("loggingProperties")) {
filePath = log4jProperties;
Type = "loggingProperties";
// throw new IOException("that was logging
selected");
@@ -201,9 +197,7 @@
}

if (session.getAttribute("authenticated") != null) {
- if (((Boolean) session.getAttribute("authenticated"))
- .booleanValue()) {
-
+ if (((Boolean)
session.getAttribute("authenticated")).booleanValue()) {
// Setting the path for the properties file
based on the type of
// properties file

@@ -213,8 +207,7 @@
// Checking firstly if the files
really exists
if ((new File(filePath)).exists()) {
properties = new
PerfsonarPropertiesImpl();
- properties
-
.loadProperties(new FileInputStream(filePath));
+ properties.loadProperties(new
FileInputStream(filePath));

session.setAttribute("properties", properties);
}
// Other wise we have a problem
@@ -228,15 +221,13 @@
}
// Else get the properties from the session
else {
- properties = (PerfsonarProperties)
session
-
.getAttribute("properties");
+ properties = (PerfsonarProperties)
session.getAttribute("properties");
}

// The user wants to save the changes to the
properties table
if ((request.getParameter("store") != null)
&&
(!request.getMethod().equalsIgnoreCase("GET"))
- && ((Boolean)
session.getAttribute("authenticated"))
-
.booleanValue()) {
+ && ((Boolean)
session.getAttribute("authenticated")).booleanValue()) {
Enumeration parameters =
request.getParameterNames();

// Creating the new Properties object
@@ -244,8 +235,7 @@
String key = (String)
parameters.nextElement();
String value = (String)
request.getParameter(key);
if (!key.equals("store")) {
- PerfsonarProperty
property = properties
-
.getProperty(key);
+ PerfsonarProperty
property = properties.getProperty(key);
if (property != null)
{

property.setValue(value);

properties.setProperty(key, property);
@@ -278,7 +268,7 @@
else {
// In this case the user
wants to add a new property
if
((request.getParameter("add") != null)) {
- // Stroring the new
property to properties
+ // Storing the new
property to properties
PerfsonarProperty
property = new PerfsonarProperty(

request.getParameter("propertyName"),

request.getParameter("propertyValue"),
@@ -286,15 +276,13 @@

request.getParameter("propertyGroup"));

properties.setProperty(property.getKey(), property);
}
- // Te user wants to remove a
property
+ // The user wants to remove a
property
if
((request.getParameter("remove") != null)) {
// Removing property
from properties
-
properties.removeProperty(request
-
.getParameter("property"));
+
properties.removeProperty(request.getParameter("property"));
}
// Showing the properties and
user options
if (properties != null) {
-

output.main_page(groupProperies(properties),Type,extraFunctionalities);
} else {
String path;
@@ -314,7 +302,7 @@
session.invalidate();
}
} else {
- // If the "authentcated" parameter has not been set
then we ask for
+ // If the "authenticated" parameter has not been set
then we ask for
// a username and password
String authorization =
request.getHeader("Authorization");
// if there is non in the headers we ask for it
@@ -335,7 +323,7 @@

// Using the authenticator to authenticate
the user
if (authenticator.authenticate(user,
password)) {
- // Authetnication was successful we
show the user all
+ // Authentication was successful we
show the user all
// properties to be configured
session.setAttribute("authenticated",
true);
if
(session.getAttribute("properties") == null) {
@@ -377,12 +365,9 @@
* @param properties
* @return
*/
- private Hashtable<String, PerfsonarProperties> groupProperies(
- PerfsonarProperties properties) {
-
+ private Hashtable<String, PerfsonarProperties>
groupProperies(PerfsonarProperties properties) {
// Check to see if any property was actually loaded
if (!properties.isEmpty()) {
-
// Creating new hashtable
Hashtable<String, PerfsonarProperties> groupTable =
new Hashtable<String, PerfsonarProperties>();
Iterator it = properties.getKeysIterator();
@@ -390,34 +375,25 @@
// groups
while (it.hasNext()) {
// Get the property
- PerfsonarProperty property =
properties.getProperty((String) it
- .next());
+ PerfsonarProperty property =
properties.getProperty((String) it.next());
// If the property group has not been set
then it is placed in a
// generic "Other" group
if (property.getGroup() == null) {
-
if (!groupTable.containsKey("Other"))
{
-
groupTable.put("Other", new
PerfsonarPropertiesImpl());
}
-
- ((PerfsonarProperties)
groupTable.get("Other"))
-
.setProperty(property.getKey(), property);
+ ((PerfsonarProperties)
groupTable.get("Other")).setProperty(property.getKey(), property);
} else {
// If the property group does not
exist as a key yet, we
// create a new key(group)
value(WizardProperties) pair
if
(!groupTable.containsKey(property.getGroup())) {
-
groupTable.put(property.getGroup(),
- new
PerfsonarPropertiesImpl());
+
groupTable.put(property.getGroup(), new PerfsonarPropertiesImpl());
}
// We add the property to the
WizardProperties of that group
- ((PerfsonarProperties)
groupTable.get(property.getGroup()))
-
.setProperty(property.getKey(), property);
+ ((PerfsonarProperties)
groupTable.get(property.getGroup())).setProperty(property.getKey(), property);
}
-
}
return groupTable;
-
} else {
return null;
}
@@ -431,11 +407,8 @@
*/

private void askForPassword(HttpServletResponse response) {
-
response.setStatus(response.SC_UNAUTHORIZED); // I.e., 401
- response.setHeader("WWW-Authenticate",
- "BASIC realm=\"perfSONAR-Admin\"");
-
+ response.setHeader("WWW-Authenticate", "BASIC
realm=\"perfSONAR-Admin\"");
}

/**
@@ -445,20 +418,16 @@
* The properties to be stored object
* @return True if successful false if something went wrong
*/
- private synchronized boolean modifyFile(PerfsonarProperties
properties,
- String filePath) {
-
+ private synchronized boolean modifyFile(PerfsonarProperties
properties, String filePath) {
try {
properties.storeProperties(new
FileOutputStream(filePath));
return true;
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
return false;
-
} catch (IOException e) {
// TODO Auto-generated catch block
return false;
-
}
}
}

Modified:
trunk/perfsonar-web-admin-0/src/main/java/perfSONARWebAdmin/auxiliary/service/HTMLOutput.java
===================================================================
---
trunk/perfsonar-web-admin-0/src/main/java/perfSONARWebAdmin/auxiliary/service/HTMLOutput.java
2014-02-10 13:55:12 UTC (rev 6491)
+++
trunk/perfsonar-web-admin-0/src/main/java/perfSONARWebAdmin/auxiliary/service/HTMLOutput.java
2014-02-10 15:36:39 UTC (rev 6492)
@@ -88,10 +88,7 @@
* The type of the properties file
* @throws IOException
*/
- public void error_page(String error, String Type)
- throws IOException {
- // TODO Auto-generated method stub
-
+ public void error_page(String error, String Type) throws IOException {
preempt();
out.println("<div class=\"info\" >");
out.println("<p>Service Administration<>");
@@ -113,11 +110,10 @@
out.println("</div>");
out.println("<div class=\"manage\">");
String tableName="Service Properties Table";
- if(!type.equals("serviceProperties")){
+ if (!type.equals("serviceProperties")) {
tableName="Logging Properties Table";
}
- out
- .println("<p
class=\"welcometextlavender\">"+tableName+"</p>");
+ out.println("<p
class=\"welcometextlavender\">"+tableName+"</p>");
out.println("<p class=\"formated_text\" >The listed settings
are optional. You can configure them to customise your installation. Place
your mouse cursor on a setting to display help.</p><br/>");
out.println("<form action=\"ServiceAdmin\" method=\"POST\">
");

@@ -138,10 +134,10 @@
PerfsonarProperties properties =
groupedProperties.get(group);
Iterator propIt = properties.getKeysIterator();

- if(change){
+ if (change) {
cssclass="darkgrey";
change=false;
- }else{
+ } else {
cssclass="lightgrey";
change=true;
}
@@ -155,8 +151,7 @@
description = description.replace(")", "]");
description = description.replace("(", "[");
description = description.replace("#", "");
- out.println("<td onmouseover=\"setTip(this,'" +
description
- + "','#C7C7F2')\" >");
+ out.println("<td onmouseover=\"setTip(this,'" +
description + "','#C7C7F2')\" >");
out.println(property.getKey());
out.println("</td>");
out.println("<td>");
@@ -178,13 +173,11 @@
description = description.replace("#", "");
out.println("<tr class=\""+cssclass+"\">");
out.println("<td/>");
- out.println("<td onmouseover=\"setTip(this,'"
+ description
- + "','#C7C7F2')\">");
+ out.println("<td onmouseover=\"setTip(this,'"
+ description + "','#C7C7F2')\">");
out.println(property.getKey());
out.println("</td>");
out.println("<td>");
- out
- .println("<input
type=\"text\" class=\"input_style_blue\" size=60 name=\""
+ out.println("<input type=\"text\"
class=\"input_style_blue\" size=60 name=\""
+
property.getKey()
+ "\"
value=\""
+
property.getValue()
@@ -200,21 +193,18 @@
out.println("<tr/>");
out.println("<tr>");
out.println("<th/><td/><td>");
- out
- .println("<input class=\"floatResetButton\"
id=\"ResetButton\" type=\"reset\" class=\"submit_button\" value=\"Cancel\"
/><input class=\"floatSubmitButton\" type=\"submit\" id=\"Button\"
name=\"store\" value=\"Apply\" class=\"submit_button\" /></td>");
+ out.println("<input class=\"floatResetButton\"
id=\"ResetButton\" type=\"reset\" class=\"submit_button\" value=\"Cancel\"
/><input class=\"floatSubmitButton\" type=\"submit\" id=\"Button\"
name=\"store\" value=\"Apply\" class=\"submit_button\" /></td>");
out.println("</tr>");
out.println("</table>");
out.println("</form>");

if (extraFunctionalities.equals("on")) {
// Options for adding and deleting a property are
added
-
out.println("<form action=\"ServiceAdmin\"
method=\"POST\"> ");
out.println("<p>");
out.println("<table>");
out.println("<tr>");
- out
- .println("<th>Add new property name
to the left column and the property value to the right column. Below add
Group and Description</th>");
+ out.println("<th>Add new property name to the left
column and the property value to the right column. Below add Group and
Description</th>");
out.println("</tr>");
out.println("</table>");
out.println("<p>");
@@ -225,11 +215,9 @@
out.println("</tr>");
out.println("<tr>");
out.println("<td>");
- out
- .println("<input type=\"text\"
size=60 name=\"propertyName\" value=\" \" />");
+ out.println("<input type=\"text\" size=60
name=\"propertyName\" value=\" \" />");
out.println("</td><td>");
- out
- .println("<input type=\"text\"
name=\"propertyValue\" size=60 value=\" \" />");
+ out.println("<input type=\"text\"
name=\"propertyValue\" size=60 value=\" \" />");
out.println("</td>");
out.println("</tr>");
out.println("<tr>");
@@ -237,17 +225,13 @@
out.println("</tr>");
out.println("<tr>");
out.println("<td>");
- out
- .println("<input type=\"text\"
size=60 name=\"propertyGroup\" value=\" \" />");
+ out.println("<input type=\"text\" size=60
name=\"propertyGroup\" value=\" \" />");
out.println("</td><td>");
- out
- .println("<input type=\"text\"
name=\"propertyDescription\" size=60 value=\" \" />");
+ out.println("<input type=\"text\"
name=\"propertyDescription\" size=60 value=\" \" />");
out.println("</td>");
out.println("<tr>");
out.println("<td>");
- out
- .println("<input "
- + " type=\"submit\"
name=\"add\" value=\"Add property\" /> ");
+ out.println("<input " + " type=\"submit\"
name=\"add\" value=\"Add property\" /> ");
out.println("</td>");
out.println("</tr>");
out.println("</table>");
@@ -268,16 +252,13 @@
Iterator propIt = pr.getKeysIterator();
while (propIt.hasNext()) {
String property = (String)
propIt.next();
- out.println("<option value=\"" +
property + "\">"
- + property +
"</option>");
+ out.println("<option value=\"" +
property + "\">" + property + "</option>");
}
out.println("</optgroup>");
}
out.println("</select></td>");
out.println("</tr>");
- out
- .println("<tr><td><input "
- + " type=\"submit\"
name=\"remove\" value=\"Remove property\" /> </td><td/></tr>");
+ out.println("<tr><td><input type=\"submit\"
name=\"remove\" value=\"Remove property\" /> </td><td/></tr>");
out.println("</table>");
out.println("</p>");
out.println("</form>");
@@ -286,7 +267,6 @@
out.println("</body>");
out.println("</html>");
out.close();
-
}

//
-----------------------------------------------------------------------
@@ -300,8 +280,7 @@
private void preempt() throws IOException {
out.println(doctype);
out.println("<html>");
- out
- .println("<head><link rel=\"stylesheet\"
type=\"text/css\" href=\"default.css\">");
+ out.println("<head><link rel=\"stylesheet\" type=\"text/css\"
href=\"default.css\">");
out.println("<title>");
out.println("perfSONAR service administration page.");
out.println("</title>");
@@ -309,6 +288,5 @@
out.println("<body>");
out.println("<script src=\"Service_Admin.js\">\n" +
"</script>\n");
out.println("<script src=\"wz_tooltip.js\">\n" +
"</script>\n");
-
}
}

Deleted:
trunk/perfsonar-web-admin-0/src/main/webapp/graphics/Paul_Hasleham.vcf
===================================================================
--- trunk/perfsonar-web-admin-0/src/main/webapp/graphics/Paul_Hasleham.vcf
2014-02-10 13:55:12 UTC (rev 6491)
+++ trunk/perfsonar-web-admin-0/src/main/webapp/graphics/Paul_Hasleham.vcf
2014-02-10 15:36:39 UTC (rev 6492)
@@ -1,9 +0,0 @@
-begin:vcard
-fn:Paul Hasleham
-n:Hasleham;Paul
-title:Web Manager
-note;quoted-printable:Paul Hasleham=0D=0A=
- Web Manager
-version:2.1
-end:vcard
-

Deleted: trunk/perfsonar-web-admin-0/src/main/webapp/graphics/Thumbs.db
===================================================================
(Binary files differ)

Modified:
trunk/perfsonar_base/src/main/java/org/perfsonar/service/measurementArchive/metadataConfig/MetadataConfigurationStorageManager.java
===================================================================
---
trunk/perfsonar_base/src/main/java/org/perfsonar/service/measurementArchive/metadataConfig/MetadataConfigurationStorageManager.java
2014-02-10 13:55:12 UTC (rev 6491)
+++
trunk/perfsonar_base/src/main/java/org/perfsonar/service/measurementArchive/metadataConfig/MetadataConfigurationStorageManager.java
2014-02-10 15:36:39 UTC (rev 6492)
@@ -116,10 +116,8 @@


for (String xmlResult1 : xmlResults) {
+ logger.debug("MetadataConfigurationStorageManager.fetch: xml
result:\n" + xmlResult1);

- //logger.debug("MetadataConfigurationStorageManager.fetch: xml
result: "
- // + xmlResults[i]);
-
if (xmlResult1.trim().isEmpty()) {
continue;
}

Modified:
trunk/perfsonar_base/src/main/java/org/perfsonar/service/measurementArchive/metadataConfig/Transformations.java
===================================================================
---
trunk/perfsonar_base/src/main/java/org/perfsonar/service/measurementArchive/metadataConfig/Transformations.java
2014-02-10 13:55:12 UTC (rev 6491)
+++
trunk/perfsonar_base/src/main/java/org/perfsonar/service/measurementArchive/metadataConfig/Transformations.java
2014-02-10 15:36:39 UTC (rev 6492)
@@ -92,8 +92,7 @@
if (query == null) {
throw new PerfSONARException(
"error.ma.query",
- "Transformations.getMetadataQuery: "
- + "Input message is null");
+ "Transformations.getMetadataQuery: Input message is null");
}

Metadata metadata;
@@ -101,13 +100,11 @@
Metadata[] metadataArray = (query.getMetadataArray());
metadata = metadataArray[0];
} catch (Exception ex) {
- logger.error("Transformations.getMetadataQuery: "
- + "Unable to get metadata from message; "
+ logger.error("Transformations.getMetadataQuery: Unable to get
metadata from message; "
+ ex.toString());
throw new PerfSONARException(
"error.ma.query",
- "Transformations.getMetadataQuery: "
- + "Unable to get metadata from message; "
+ "Transformations.getMetadataQuery: Unable to get metadata
from message; "
+ ex.toString());
}

@@ -119,17 +116,15 @@
} catch (NullPointerException npex) {
throw new PerfSONARException(
"error.ma.query",
- "Transformations.getMetadataQuery: "
- + "eventType in the request is null");
+ "Transformations.getMetadataQuery: eventType in the
request is null");
}
} else {
throw new PerfSONARException(
"error.ma.query",
- "Transformations.getMetadataQuery: "
- + "metadata is missing in the request");
+ "Transformations.getMetadataQuery: metadata is missing in
the request");
}

- // getting an appropriate MetadataQueryGenerator to genarate correct
metadata query
+ // getting an appropriate MetadataQueryGenerator to generate correct
metadata query
MetadataQueryGenerator metadataQueryGenerator =

MetadataQueryGeneratorFactory.getMetadataQueryGenerator(eventType);

@@ -140,16 +135,12 @@
throw new PerfSONARException(pex.getResultCode(),
pex.getMessage());
} catch (Exception ex) {
logger.error("Transformations.getMetadataQuery: "
- + "Unable to generate xquery statement "
- + "for the metadata configuration "
- + "from the request metadata. "
- + ex.toString());
+ + "Unable to generate xquery statement for the metadata
configuration "
+ + "from the request metadata. " + ex.toString());
throw new PerfSONARException(
"error.ma.query",
- "Unable to generate xquery statement "
- + "for the metadata configuration "
- + "from the request metadata. "
- + ex.toString());
+ "Unable to generate xquery statement for the metadata
configuration "
+ + "from the request metadata. " + ex.toString());
}

return mq;

Modified:
trunk/perfsonar_base/src/main/java/org/perfsonar/service/measurementArchive/metadataConfig/queryGenerator/IperfQueryGenerator.java
===================================================================
---
trunk/perfsonar_base/src/main/java/org/perfsonar/service/measurementArchive/metadataConfig/queryGenerator/IperfQueryGenerator.java
2014-02-10 13:55:12 UTC (rev 6491)
+++
trunk/perfsonar_base/src/main/java/org/perfsonar/service/measurementArchive/metadataConfig/queryGenerator/IperfQueryGenerator.java
2014-02-10 15:36:39 UTC (rev 6492)
@@ -32,6 +32,7 @@
{
protected LoggerComponent logger = null;

+ // All the parameters understood by the SQL MA for iperf storage
private final String[] parameters = {"format", "protocol", "windowSize",
"timeDuration", "valueUnits",
"numBytesUnits" };

@@ -69,6 +70,7 @@
+ "Unable to get metadata from the message; " +
ex.toString());
}

+ logger.debug("Trying to build an iperf metadata query.");
eventType = metadata.getEventType().getEventType().trim();

Parameter keywordParameter = metadata.getParameterByName("keyword");
@@ -83,6 +85,7 @@
}
}

+ logger.debug("Trying to extract parameters.");
// parameters
Map<String, String> iperfParametersMap = new HashMap<String,
String>();
Parameters params;
@@ -93,7 +96,10 @@
// nmwg:parameters
params = metadata.getParameters();
}
+
if (params != null) {
+ logger.debug("All parameters received for the iperf metadata
query: " + params.getParameterMap().keySet().toString());
+ // We keep only parameters that are meaningful to us
for (String parameter : parameters) {
if (params.getParameterByName(parameter) != null) {
iperfParametersMap.put(parameter,
@@ -102,6 +108,7 @@
}
}
}
+ logger.debug("Parameters used for the iperf metadata query: " +
iperfParametersMap);

Src sourceElement;
Dst destinationElement;



  • [pS-dev] [GEANT/SA2/ps-java-services] r6492 - in trunk: perfsonar-web-admin-0/src/main/java/perfSONARW ebAdmin/admin/service perfsonar-web-admin-0/src/main/java/ perfSONARWebAdmin/auxiliary/service perfsonar-web-admin-0/ src/main/webapp/graphics perfsonar_base/src/main/java/or g/perfsonar/service/measurementArchive/metadataConfig perf sonar_base/src/main/java/org/perfsonar/service/measureme ntArchive/metadataConfig/queryGenerator, svn-noreply, 02/10/2014

Archive powered by MHonArc 2.6.16.

Top of Page