001: /*
002: * The contents of this file are subject to the
003: * Mozilla Public License Version 1.1 (the "License");
004: * you may not use this file except in compliance with the License.
005: * You may obtain a copy of the License at http://www.mozilla.org/MPL/
006: *
007: * Software distributed under the License is distributed on an "AS IS"
008: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
009: * See the License for the specific language governing rights and
010: * limitations under the License.
011: *
012: * The Initial Developer of the Original Code is Simulacra Media Ltd.
013: * Portions created by Simulacra Media Ltd are Copyright (C) Simulacra Media Ltd, 2004.
014: *
015: * All Rights Reserved.
016: *
017: * Contributor(s):
018: *
019: * Created: 29-Nov-2004 by jejking
020: * Version: $Revision: 1.5 $
021: * Last Updated: $Date: 2004/12/24 12:10:45 $
022: */
023: package org.openharmonise.dav.server.webservice;
024:
025: import java.io.File;
026: import java.io.FileInputStream;
027: import java.io.FileOutputStream;
028: import java.io.IOException;
029: import java.rmi.RemoteException;
030: import java.util.Iterator;
031: import java.util.zip.Deflater;
032: import java.util.zip.ZipEntry;
033: import java.util.zip.ZipOutputStream;
034:
035: import javax.xml.parsers.FactoryConfigurationError;
036: import javax.xml.parsers.ParserConfigurationException;
037:
038: import org.openharmonise.commons.dsi.*;
039: import org.openharmonise.commons.net.Email;
040: import org.openharmonise.commons.xml.*;
041: import org.openharmonise.commons.xml.namespace.NamespaceType;
042: import org.openharmonise.dav.server.utils.*;
043: import org.openharmonise.rm.DataAccessException;
044: import org.openharmonise.rm.config.ConfigException;
045: import org.openharmonise.rm.config.ConfigSettings;
046: import org.openharmonise.rm.dsi.DataStoreInterfaceFactory;
047: import org.openharmonise.rm.factory.HarmoniseFactoryException;
048: import org.openharmonise.rm.factory.HarmoniseObjectFactory;
049: import org.openharmonise.rm.publishing.*;
050: import org.openharmonise.rm.resources.AbstractChildObject;
051: import org.openharmonise.rm.resources.AbstractParentObject;
052: import org.openharmonise.rm.resources.content.Section;
053: import org.openharmonise.rm.resources.lifecycle.Status;
054: import org.openharmonise.rm.resources.metadata.properties.PropertyGroup;
055: import org.openharmonise.rm.resources.publishing.WebPage;
056: import org.w3c.dom.*;
057: import org.xml.sax.SAXException;
058:
059: /**
060: *
061: * Webservice to publish a Harmonise Page using a State element (containing the page id),
062: * a Harmonise Page template or a combination of both. Note that the presense of a
063: * Harmonise Page template would overide the presense of a Page id in the State.
064: * @author matt treanor
065: * @version $Revision: 1.5 $
066: *
067: */
068: public class PublishService {
069: private static final String ATTRIB_HREF = "href";
070: protected AbstractDataStoreInterface m_dsi = null;
071: static final String TAG_HARMONISE_PUBLISH_SERVICE = "HarmonisePublishService";
072: static final String PNAME_UPLOADED_TEMPFILE_DIR = "UPLOADED_TEMPFILE_DIR";
073: static final String PNAME_EMAIL_HOST = "EMAIL_HOST";
074: static final String DOCUMENT_ROOT_PATH = "/root/documents";
075: static final String PROP_GROUP_ROOT_PATH = "/root/props";
076:
077: /**
078: *
079: * @param sXml
080: * @return
081: * @throws RemoteException
082: */
083: public String publish(String sXml) throws RemoteException {
084: String sResult = null;
085: try {
086: Document doc = XMLDocument.getXMLDocumentFromString(sXml);
087: Element inputRoot = doc.getDocumentElement();
088: String sTagName = inputRoot.getTagName();
089: if (sTagName.equals(TAG_HARMONISE_PUBLISH_SERVICE) == false) {
090: throw new RemoteException("Root element must be "
091: + TAG_HARMONISE_PUBLISH_SERVICE);
092: }
093: convertWebdavPaths(doc);
094: NodeList nodes = inputRoot
095: .getElementsByTagName(State.TAG_STATE);
096: Element stateEl = (Element) nodes.item(0);
097: State state = null;
098: if (stateEl != null) {
099: Document stateXml = new XMLDocument();
100: stateXml.appendChild(XMLUtils.copyNode(stateEl,
101: stateXml));
102: state = new State(stateXml, getDataStoreInterface());
103: } else {
104: state = new State(getDataStoreInterface());
105: Element el = state.createElement(State.TAG_STATE);
106: state.appendChild(el);
107: }
108: nodes = inputRoot
109: .getElementsByTagName(WebPage.TAG_HARMONISE);
110: Element ohEl = (Element) nodes.item(0);
111: WebPageEngine engine = new WebPageEngine(this
112: .getDataStoreInterface());
113: HarmoniseOutput out = null;
114: WebPage page = null;
115: if (ohEl != null) {
116: out = engine.createXML(ohEl, state);
117: } else {
118: nodes = stateEl.getElementsByTagName(WebPage.TAG_PAGE);
119: Element pageEl = (Element) nodes.item(0);
120: if (pageEl != null) {
121: String sId = pageEl.getAttribute(WebPage.ATTRIB_ID);
122: if (sId != null) {
123: int nId = Integer.parseInt(sId);
124: page = new WebPage(getDataStoreInterface(), nId);
125: System.out.println("Found page "
126: + page.getName());
127: }
128: }
129: out = engine.createXML(page, state);
130: }
131: XMLPrettyPrint printer = new XMLPrettyPrint();
132: printer.setNamespaceAware(true);
133: Element outEL = out.getDocumentElement();
134: sResult = printer.printNode(outEL);
135: } catch (Exception e) {
136: throw new RemoteException(e.getLocalizedMessage());
137: }
138: return sResult;
139: }
140:
141: public void publishContent(String sEmail, boolean bShowContent,
142: boolean bShowMetadata) throws RemoteException {
143: String sResult = null;
144: try {
145: String sTempDir = ConfigSettings
146: .getProperty(PNAME_UPLOADED_TEMPFILE_DIR);
147: String sZipPath = sTempDir + "/HarmoniseContent.zip";
148: FileOutputStream fos = new FileOutputStream(sZipPath);
149: ZipOutputStream zos = new ZipOutputStream(fos);
150: zos.setLevel(Deflater.DEFAULT_COMPRESSION);
151:
152: if (bShowContent) {
153: String sHarmonisePath = sTempDir + "/HarmoniseContent";
154:
155: File harmoniseDir = new File(sHarmonisePath);
156: harmoniseDir.mkdir();
157:
158: AbstractParentObject docRoot = (AbstractParentObject) HarmoniseObjectFactory
159: .instantiateHarmoniseObject(
160: getDataStoreInterface(), Section.class
161: .getName(), DOCUMENT_ROOT_PATH);
162: writeCollection(docRoot, harmoniseDir);
163:
164: recurseDir(zos, sHarmonisePath);
165:
166: harmoniseDir.delete();
167: }
168:
169: if (bShowMetadata) {
170: HarmoniseOutput out = new HarmoniseOutput(
171: getDataStoreInterface());
172:
173: Element propGroupEl = out.createElement("Metadata");
174: out.appendChild(propGroupEl);
175:
176: PropertyGroup propGroupRoot = (PropertyGroup) HarmoniseObjectFactory
177: .instantiateHarmoniseObject(
178: getDataStoreInterface(),
179: PropertyGroup.class.getName(),
180: PROP_GROUP_ROOT_PATH);
181: writePropertyGroup(propGroupRoot, out
182: .getDocumentElement(), out);
183:
184: String sMetadataPath = sTempDir + "/Metadata.xml";
185: File metadataFile = new File(sMetadataPath);
186:
187: XMLPrettyPrint pp = new XMLPrettyPrint();
188: pp.printNodeToFile(out.getDocumentElement(),
189: metadataFile);
190: addToZip(zos, metadataFile.getPath());
191:
192: metadataFile.delete();
193: }
194: zos.close();
195: fos.close();
196: if (bShowContent || bShowMetadata) {
197: File zipFile = new File(sZipPath);
198: mailFile(sEmail, zipFile);
199: }
200:
201: } catch (Exception e) {
202: throw new RemoteException(e.getLocalizedMessage());
203: }
204: }
205:
206: private void recurseDir(ZipOutputStream zos, String filePath)
207: throws ConfigException, IOException {
208: File file = new File(filePath);
209: File[] fileList = file.listFiles();
210: for (int i = 0; i < fileList.length; i++) {
211: if (fileList[i].isDirectory()) {
212: recurseDir(zos, fileList[i].getPath());
213: } else if (fileList[i].isFile()) {
214: // Call the zipFunc function
215: addToZip(zos, fileList[i].getPath());
216: }
217: }
218: }
219:
220: private void addToZip(ZipOutputStream zos, String filePath)
221: throws IOException, ConfigException {
222: FileInputStream in = new FileInputStream(filePath);
223: String sTempDir = ConfigSettings
224: .getProperty(PNAME_UPLOADED_TEMPFILE_DIR);
225:
226: String zipPath = filePath.substring(sTempDir.length() - 1);
227: zos.putNextEntry(new ZipEntry(zipPath));
228: byte[] buffer = new byte[18024];
229: int len;
230: while ((len = in.read(buffer)) > 0) {
231: zos.write(buffer, 0, len);
232: }
233: }
234:
235: private void writeCollection(AbstractParentObject parent,
236: File parentDir) throws ConfigException,
237: DataAccessException, PublishException, StateException,
238: RemoteException, SAXException, IOException,
239: ParserConfigurationException, FactoryConfigurationError {
240: File dir = new File(parentDir.getAbsolutePath() + "/"
241: + parent.getName());
242: dir.mkdir();
243: Iterator iter = parent.getChildren().iterator();
244: while (iter.hasNext()) {
245: AbstractChildObject child = (AbstractChildObject) iter
246: .next();
247:
248: if (child instanceof AbstractParentObject) {
249: AbstractParentObject sub = (AbstractParentObject) child;
250: writeCollection(sub, dir);
251: } else if (child.getStatus() == Status.APPROVED) {
252: writeDocument(child, getResourceTemplate()
253: .getDocumentElement(), dir);
254: }
255: }
256:
257: }
258:
259: private void writeDocument(AbstractChildObject resource,
260: Element templateRoot, File parentDir)
261: throws DataAccessException, PublishException, SAXException,
262: IOException, ParserConfigurationException,
263: FactoryConfigurationError, StateException, RemoteException {
264: File file = new File(parentDir.getAbsolutePath() + "/"
265: + resource.getName() + ".xml");
266:
267: HarmoniseOutput out = new HarmoniseOutput(
268: getDataStoreInterface());
269: Element elResource = resource.publish(templateRoot, out,
270: getState());
271:
272: XMLPrettyPrint pp = new XMLPrettyPrint();
273: pp.printNodeToFile(elResource, file);
274: }
275:
276: private void writePropertyGroup(PropertyGroup propGroup,
277: Element topEl, HarmoniseOutput out)
278: throws HarmoniseFactoryException, ConfigException,
279: DataAccessException, PublishException, StateException,
280: RemoteException, SAXException, IOException,
281: ParserConfigurationException, FactoryConfigurationError {
282: Element docEl = propGroup.publish(getPropertyGroupTemplate()
283: .getDocumentElement(), out, getState());
284:
285: Iterator iter = propGroup.getChildren().iterator();
286: while (iter.hasNext()) {
287: AbstractChildObject child = (AbstractChildObject) iter
288: .next();
289:
290: if (child instanceof PropertyGroup) {
291: PropertyGroup sub = (PropertyGroup) child;
292: writePropertyGroup(sub, topEl, out);
293: } else if (child.getStatus() == Status.APPROVED) {
294: writeProperty(child, getPropertyTemplate()
295: .getDocumentElement(), docEl, out);
296: }
297: }
298: topEl.appendChild(docEl);
299: }
300:
301: private void writeProperty(AbstractChildObject prop,
302: Element templateRoot, Element topEl, HarmoniseOutput out)
303: throws PublishException, StateException, RemoteException,
304: SAXException, IOException, ParserConfigurationException,
305: FactoryConfigurationError {
306: Element docEl = prop.publish(getPropertyTemplate()
307: .getDocumentElement(), out, getState());
308: topEl.appendChild(docEl);
309: }
310:
311: private AbstractDataStoreInterface getDataStoreInterface()
312: throws RemoteException {
313: if (m_dsi == null) {
314: try {
315: m_dsi = DataStoreInterfaceFactory
316: .getDataStoreInterface();
317: } catch (DataStoreException e) {
318: throw new RemoteException(e.getLocalizedMessage(), e);
319: }
320: }
321: return m_dsi;
322: }
323:
324: private void convertWebdavPaths(Document doc) throws DOMException,
325: NameResolverException {
326: //translate webdav paths to real ones
327: NodeList pathNodes = doc
328: .getElementsByTagName(AbstractChildObject.TAG_PATH);
329: Element curElm = null;
330: String sPath = null;
331: //Element parentEl = null;
332: for (int i = 0; i < pathNodes.getLength(); i++) {
333: curElm = (Element) pathNodes.item(i); // get the current path
334: Text pathText = (Text) curElm.getFirstChild();
335: // get the first child
336: if (pathText != null) {
337: sPath = pathText.getData();
338: if (sPath
339: .startsWith(HarmoniseNameResolver.URL_SEPARATOR)) {
340: String sRealPath = HarmoniseNameResolver
341: .getRealPath(sPath);
342:
343: if (sRealPath != null) {
344: pathText.setData(sRealPath);
345: }
346: }
347: }
348: }
349: //translate webdav paths in xincludes
350: NodeList xincludes = doc.getElementsByTagNameNS(
351: NamespaceType.XINCLUDE.getURI(), "include");
352: String sHref = null;
353: for (int i = 0; i < xincludes.getLength(); i++) {
354: curElm = (Element) xincludes.item(i);
355: // get the current path
356: Attr hrefAttr = (Attr) curElm.getAttributeNode(ATTRIB_HREF);
357: // get the first child
358: sHref = hrefAttr.getValue();
359: if (sHref.startsWith(HarmoniseNameResolver.URL_SEPARATOR
360: + HarmoniseNameResolver.WEBDAV_ROOT_MARKER)) {
361: hrefAttr.setValue(HarmoniseNameResolver
362: .getRealPath(sHref));
363: }
364: }
365: }
366:
367: private void mailFile(String recipient_address, File file)
368: throws ConfigException, Exception {
369: String sender_address = "HarmoniseServer";
370: String message = "Contents of the Harmonise Server";
371: String subject = "Harmonise Content";
372: Email email = new Email(ConfigSettings
373: .getProperty(PNAME_EMAIL_HOST), recipient_address,
374: sender_address, subject, message, file);
375: if (email.send() == false) {
376: throw new RemoteException(
377: "There was a problem emailing the file "
378: + file.getPath());
379: } else {
380: file.delete();
381: }
382: }
383:
384: public static void main(String args[]) {
385: String sReturn = "";
386: try {
387: PublishService service = new PublishService();
388: String sXml = null;
389:
390: sXml = "<HarmonisePublishService><State>"
391: + "<Page id=\"1000\"/>"
392: + "</State></HarmonisePublishService>";
393: sReturn = service.publish(sXml);
394: } catch (RemoteException e) {
395: // TODO Auto-generated catch block
396: System.out.println(e.getLocalizedMessage());
397: }
398: System.out.println(sReturn);
399: System.exit(0);
400: }
401:
402: private Document getResourceTemplate() throws SAXException,
403: IOException, ParserConfigurationException,
404: FactoryConfigurationError {
405: String sXml = "<HarmoniseObject><Name/><DisplayName/><Summary/><Content/><Profile default='true'><AllPropertyInstances/></Profile><Status/></HarmoniseObject>";
406: return XMLDocument.getXMLDocumentFromString(sXml);
407: }
408:
409: private Document getPropertyGroupTemplate() throws SAXException,
410: IOException, ParserConfigurationException,
411: FactoryConfigurationError {
412: String sXml = "<PropertyGroup><Name/><Summary/></PropertyGroup>";
413: return XMLDocument.getXMLDocumentFromString(sXml);
414: }
415:
416: private Document getPropertyTemplate() throws SAXException,
417: IOException, ParserConfigurationException,
418: FactoryConfigurationError {
419: String sXml = "<Property><DomainList/><Range><RangeDetails/><RangeObject/></Range></Property>";
420: return XMLDocument.getXMLDocumentFromString(sXml);
421: }
422:
423: private State getState() throws StateException, RemoteException {
424: State state = new State(getDataStoreInterface());
425: return state;
426: }
427: }
|