001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package com.sun.servicetag;
043:
044: import java.io.*;
045: import java.net.URL;
046: import java.util.Collection;
047: import java.util.Map;
048: import java.util.Set;
049:
050: import org.w3c.dom.Document;
051: import org.w3c.dom.Element;
052: import org.w3c.dom.Node;
053: import org.w3c.dom.NodeList;
054: import org.xml.sax.SAXException;
055: import org.xml.sax.InputSource;
056:
057: import javax.xml.XMLConstants;
058: import javax.xml.parsers.DocumentBuilder;
059: import javax.xml.parsers.DocumentBuilderFactory;
060:
061: import javax.xml.parsers.ParserConfigurationException;
062: import javax.xml.validation.Schema;
063: import javax.xml.validation.SchemaFactory;
064: import javax.xml.validation.Validator;
065:
066: // For write operation
067: import javax.xml.transform.OutputKeys;
068: import javax.xml.transform.Transformer;
069: import javax.xml.transform.TransformerException;
070: import javax.xml.transform.TransformerFactory;
071: import javax.xml.transform.TransformerConfigurationException;
072: import javax.xml.transform.dom.DOMSource;
073: import javax.xml.transform.stream.StreamResult;
074:
075: /**
076: * XML Support Class for Product Registration.
077: */
078: class RegistrationDocument {
079:
080: private static final String REGISTRATION_DATA_SCHEMA = "/com/sun/servicetag/resources/product_registration.xsd";
081: private static final String REGISTRATION_DATA_VERSION = "1.0";
082: private static final String SERVICE_TAG_VERSION = "1.0";
083: final static String ST_NODE_REGISTRATION_DATA = "registration_data";
084: final static String ST_ATTR_REGISTRATION_VERSION = "version";
085: final static String ST_NODE_ENVIRONMENT = "environment";
086: final static String ST_NODE_HOSTNAME = "hostname";
087: final static String ST_NODE_HOST_ID = "hostId";
088: final static String ST_NODE_OS_NAME = "osName";
089: final static String ST_NODE_OS_VERSION = "osVersion";
090: final static String ST_NODE_OS_ARCH = "osArchitecture";
091: final static String ST_NODE_SYSTEM_MODEL = "systemModel";
092: final static String ST_NODE_SYSTEM_MANUFACTURER = "systemManufacturer";
093: final static String ST_NODE_CPU_MANUFACTURER = "cpuManufacturer";
094: final static String ST_NODE_SERIAL_NUMBER = "serialNumber";
095: final static String ST_NODE_REGISTRY = "registry";
096: final static String ST_ATTR_REGISTRY_URN = "urn";
097: final static String ST_ATTR_REGISTRY_VERSION = "version";
098: final static String ST_NODE_SERVICE_TAG = "service_tag";
099: final static String ST_NODE_INSTANCE_URN = "instance_urn";
100: final static String ST_NODE_PRODUCT_NAME = "product_name";
101: final static String ST_NODE_PRODUCT_VERSION = "product_version";
102: final static String ST_NODE_PRODUCT_URN = "product_urn";
103: final static String ST_NODE_PRODUCT_PARENT_URN = "product_parent_urn";
104: final static String ST_NODE_PRODUCT_PARENT = "product_parent";
105: final static String ST_NODE_PRODUCT_DEFINED_INST_ID = "product_defined_inst_id";
106: final static String ST_NODE_PRODUCT_VENDOR = "product_vendor";
107: final static String ST_NODE_PLATFORM_ARCH = "platform_arch";
108: final static String ST_NODE_TIMESTAMP = "timestamp";
109: final static String ST_NODE_CONTAINER = "container";
110: final static String ST_NODE_SOURCE = "source";
111: final static String ST_NODE_INSTALLER_UID = "installer_uid";
112:
113: static RegistrationData load(InputStream in) throws IOException {
114: Document document = initializeDocument(in);
115:
116: // Gets the registration URN
117: Element root = getRegistrationDataRoot(document);
118: Element registryRoot = getSingletonElementFromRoot(root,
119: ST_NODE_REGISTRY);
120: String urn = registryRoot.getAttribute(ST_ATTR_REGISTRY_URN);
121:
122: // Construct a new RegistrationData object from the DOM tree
123: // Initialize the environment map and service tags
124: RegistrationData regData = new RegistrationData(urn);
125: addServiceTags(registryRoot, regData);
126:
127: Element envRoot = getSingletonElementFromRoot(root,
128: ST_NODE_ENVIRONMENT);
129: buildEnvironmentMap(envRoot, regData);
130: return regData;
131: }
132:
133: static void store(OutputStream os, RegistrationData registration)
134: throws IOException {
135: // create a new document with the root node
136: Document document = initializeDocument();
137:
138: // create the nodes for the environment map and the service tags
139: // in the registration data
140: addEnvironmentNodes(document, registration.getEnvironmentMap());
141: addServiceTagRegistry(document, registration
142: .getRegistrationURN(), registration.getServiceTags());
143: transform(document, os);
144: }
145:
146: // initialize a document from an input stream
147: private static Document initializeDocument(InputStream in)
148: throws IOException {
149: DocumentBuilderFactory factory = DocumentBuilderFactory
150: .newInstance();
151: factory.setNamespaceAware(true);
152: try {
153: // XML schema for validation
154: SchemaFactory sf = SchemaFactory
155: .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
156: URL xsdUrl = RegistrationDocument.class
157: .getResource(REGISTRATION_DATA_SCHEMA);
158: Schema schema = sf.newSchema(xsdUrl);
159: Validator validator = schema.newValidator();
160:
161: DocumentBuilder builder = factory.newDocumentBuilder();
162: Document doc = builder.parse(new InputSource(in));
163: validator.validate(new DOMSource(doc));
164: return doc;
165: } catch (SAXException sxe) {
166: IllegalArgumentException e = new IllegalArgumentException(
167: "Error generated in parsing");
168: e.initCause(sxe);
169: throw e;
170: } catch (ParserConfigurationException pce) {
171: // Parser with specific options can't be built
172: // should not reach here
173: InternalError x = new InternalError(
174: "Error in creating the new document");
175: x.initCause(pce);
176: throw x;
177: }
178: }
179:
180: // initialize a new document for the registration data
181: private static Document initializeDocument() throws IOException {
182: DocumentBuilderFactory factory = DocumentBuilderFactory
183: .newInstance();
184: factory.setNamespaceAware(true);
185: try {
186: DocumentBuilder builder = factory.newDocumentBuilder();
187: Document doc = builder.newDocument();
188:
189: // initialize the document with the registration_data root
190: Element root = doc.createElement(ST_NODE_REGISTRATION_DATA);
191: doc.appendChild(root);
192: root.setAttribute(ST_ATTR_REGISTRATION_VERSION,
193: REGISTRATION_DATA_VERSION);
194:
195: return doc;
196: } catch (ParserConfigurationException pce) {
197: // Parser with specified options can't be built
198: // should not reach here
199: InternalError x = new InternalError(
200: "Error in creating the new document");
201: x.initCause(pce);
202: throw x;
203: }
204: }
205:
206: // Transform the current DOM tree with the given output stream.
207: private static void transform(Document document, OutputStream os) {
208: try {
209: // Use a Transformer for output
210: TransformerFactory tFactory = TransformerFactory
211: .newInstance();
212: tFactory.setAttribute("indent-number", new Integer(3));
213:
214: Transformer transformer = tFactory.newTransformer();
215:
216: transformer.setOutputProperty(OutputKeys.INDENT, "yes");
217: transformer.setOutputProperty(OutputKeys.METHOD, "xml");
218: transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
219: transformer.setOutputProperty(OutputKeys.STANDALONE, "yes");
220: transformer.transform(new DOMSource(document),
221: new StreamResult(new BufferedWriter(
222: new OutputStreamWriter(os, "UTF-8"))));
223: } catch (UnsupportedEncodingException ue) {
224: // Should not reach here
225: InternalError x = new InternalError(
226: "Error generated during transformation");
227: x.initCause(ue);
228: throw x;
229: } catch (TransformerConfigurationException tce) {
230: // Error generated by the parser
231: // Should not reach here
232: InternalError x = new InternalError(
233: "Error in creating the new document");
234: x.initCause(tce);
235: throw x;
236: } catch (TransformerException te) {
237: // Error generated by the transformer
238: InternalError x = new InternalError(
239: "Error generated during transformation");
240: x.initCause(te);
241: throw x;
242: }
243: }
244:
245: private static void addServiceTagRegistry(Document document,
246: String registryURN, Set<ServiceTag> svcTags) {
247: // add service tag registry node and its attributes
248: Element reg = document.createElement(ST_NODE_REGISTRY);
249: reg.setAttribute(ST_ATTR_REGISTRY_URN, registryURN);
250: reg.setAttribute(ST_ATTR_REGISTRY_VERSION, SERVICE_TAG_VERSION);
251:
252: Element root = getRegistrationDataRoot(document);
253: root.appendChild(reg);
254:
255: // adds the elements for the service tags
256: for (ServiceTag st : svcTags) {
257: addServiceTagElement(document, reg, st);
258: }
259: }
260:
261: private static void addServiceTagElement(Document document,
262: Element registryRoot, ServiceTag st) {
263: Element svcTag = document.createElement(ST_NODE_SERVICE_TAG);
264: registryRoot.appendChild(svcTag);
265: addChildElement(document, svcTag, ST_NODE_INSTANCE_URN, st
266: .getInstanceURN());
267: addChildElement(document, svcTag, ST_NODE_PRODUCT_NAME, st
268: .getProductName());
269: addChildElement(document, svcTag, ST_NODE_PRODUCT_VERSION, st
270: .getProductVersion());
271: addChildElement(document, svcTag, ST_NODE_PRODUCT_URN, st
272: .getProductURN());
273: addChildElement(document, svcTag, ST_NODE_PRODUCT_PARENT_URN,
274: st.getProductParentURN());
275: addChildElement(document, svcTag, ST_NODE_PRODUCT_PARENT, st
276: .getProductParent());
277: addChildElement(document, svcTag,
278: ST_NODE_PRODUCT_DEFINED_INST_ID, st
279: .getProductDefinedInstanceID());
280: addChildElement(document, svcTag, ST_NODE_PRODUCT_VENDOR, st
281: .getProductVendor());
282: addChildElement(document, svcTag, ST_NODE_PLATFORM_ARCH, st
283: .getPlatformArch());
284: addChildElement(document, svcTag, ST_NODE_TIMESTAMP, Util
285: .formatTimestamp(st.getTimestamp()));
286: addChildElement(document, svcTag, ST_NODE_CONTAINER, st
287: .getContainer());
288: addChildElement(document, svcTag, ST_NODE_SOURCE, st
289: .getSource());
290: addChildElement(document, svcTag, ST_NODE_INSTALLER_UID, String
291: .valueOf(st.getInstallerUID()));
292: }
293:
294: private static void addChildElement(Document document,
295: Element root, String element, String text) {
296: Element node = document.createElement(element);
297: node.appendChild(document.createTextNode(text));
298: root.appendChild(node);
299: }
300:
301: // Constructs service tags from the document
302: private static void addServiceTags(Element registryRoot,
303: RegistrationData registration) {
304: NodeList children = registryRoot
305: .getElementsByTagName(ST_NODE_SERVICE_TAG);
306: int length = (children == null ? 0 : children.getLength());
307: for (int i = 0; i < length; i++) {
308: Element svcTagElement = (Element) children.item(i);
309: ServiceTag st = getServiceTag(svcTagElement);
310: registration.addServiceTag(st);
311: }
312: }
313:
314: // build environment map from the document
315: private static void buildEnvironmentMap(Element envRoot,
316: RegistrationData registration) {
317: registration.setEnvironment(ST_NODE_HOSTNAME, getTextValue(
318: envRoot, ST_NODE_HOSTNAME));
319: registration.setEnvironment(ST_NODE_HOST_ID, getTextValue(
320: envRoot, ST_NODE_HOST_ID));
321: registration.setEnvironment(ST_NODE_OS_NAME, getTextValue(
322: envRoot, ST_NODE_OS_NAME));
323: registration.setEnvironment(ST_NODE_OS_VERSION, getTextValue(
324: envRoot, ST_NODE_OS_VERSION));
325: registration.setEnvironment(ST_NODE_OS_ARCH, getTextValue(
326: envRoot, ST_NODE_OS_ARCH));
327: registration.setEnvironment(ST_NODE_SYSTEM_MODEL, getTextValue(
328: envRoot, ST_NODE_SYSTEM_MODEL));
329: registration.setEnvironment(ST_NODE_SYSTEM_MANUFACTURER,
330: getTextValue(envRoot, ST_NODE_SYSTEM_MANUFACTURER));
331: registration.setEnvironment(ST_NODE_CPU_MANUFACTURER,
332: getTextValue(envRoot, ST_NODE_CPU_MANUFACTURER));
333: registration.setEnvironment(ST_NODE_SERIAL_NUMBER,
334: getTextValue(envRoot, ST_NODE_SERIAL_NUMBER));
335: }
336:
337: // add the nodes representing the environment map in the document
338: private static void addEnvironmentNodes(Document document,
339: Map<String, String> envMap) {
340: Element root = getRegistrationDataRoot(document);
341: Element env = document.createElement(ST_NODE_ENVIRONMENT);
342: root.appendChild(env);
343: Set<Map.Entry<String, String>> keys = envMap.entrySet();
344: for (Map.Entry<String, String> entry : keys) {
345: addChildElement(document, env, entry.getKey(), entry
346: .getValue());
347: }
348: }
349:
350: private static Element getRegistrationDataRoot(Document doc) {
351: Element root = doc.getDocumentElement();
352: if (!root.getNodeName().equals(ST_NODE_REGISTRATION_DATA)) {
353: throw new IllegalArgumentException("Not a "
354: + ST_NODE_REGISTRATION_DATA + " node \""
355: + root.getNodeName() + "\"");
356: }
357: return root;
358: }
359:
360: private static Element getSingletonElementFromRoot(Element root,
361: String name) {
362: NodeList children = root.getElementsByTagName(name);
363: int length = (children == null ? 0 : children.getLength());
364: if (length != 1) {
365: throw new IllegalArgumentException("Invalid number of "
366: + name + " nodes = " + length);
367: }
368: Element e = (Element) children.item(0);
369: if (!e.getNodeName().equals(name)) {
370: throw new IllegalArgumentException("Not a " + name
371: + " node \"" + e.getNodeName() + "\"");
372: }
373: return e;
374: }
375:
376: // Constructs one ServiceTag instance from a service tag element root
377: private static ServiceTag getServiceTag(Element svcTagElement) {
378: return new ServiceTag(getTextValue(svcTagElement,
379: ST_NODE_INSTANCE_URN), getTextValue(svcTagElement,
380: ST_NODE_PRODUCT_NAME), getTextValue(svcTagElement,
381: ST_NODE_PRODUCT_VERSION), getTextValue(svcTagElement,
382: ST_NODE_PRODUCT_URN), getTextValue(svcTagElement,
383: ST_NODE_PRODUCT_PARENT), getTextValue(svcTagElement,
384: ST_NODE_PRODUCT_PARENT_URN), getTextValue(
385: svcTagElement, ST_NODE_PRODUCT_DEFINED_INST_ID),
386: getTextValue(svcTagElement, ST_NODE_PRODUCT_VENDOR),
387: getTextValue(svcTagElement, ST_NODE_PLATFORM_ARCH),
388: getTextValue(svcTagElement, ST_NODE_CONTAINER),
389: getTextValue(svcTagElement, ST_NODE_SOURCE), Util
390: .getIntValue(getTextValue(svcTagElement,
391: ST_NODE_INSTALLER_UID)), Util
392: .parseTimestamp(getTextValue(svcTagElement,
393: ST_NODE_TIMESTAMP)));
394: }
395:
396: private static String getTextValue(Element e, String tagName) {
397: String value = "";
398: NodeList nl = e.getElementsByTagName(tagName);
399: if (nl != null && nl.getLength() > 0) {
400: Element el = (Element) nl.item(0);
401: Node node = el.getFirstChild();
402: if (node != null) {
403: value = node.getNodeValue();
404: }
405: }
406: return value;
407: }
408: }
|