diff --git a/config/alfresco/templates/webscripts/org/alfresco/indexall.get.html.ftl b/config/alfresco/templates/webscripts/org/alfresco/indexall.get.html.ftl index 13760d50a3..f689723a65 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/indexall.get.html.ftl +++ b/config/alfresco/templates/webscripts/org/alfresco/indexall.get.html.ftl @@ -38,7 +38,7 @@ Format Style:${desc.formatStyle} Default Format:${desc.defaultFormat!"Determined at run-time"} - Id:${desc.id} + Id:${desc.id} Description:${desc.storePath}/${desc.descPath}
diff --git a/config/alfresco/templates/webscripts/org/alfresco/indexpackage.get.html.ftl b/config/alfresco/templates/webscripts/org/alfresco/indexpackage.get.html.ftl index cc085a5cbb..6dfc1aaa69 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/indexpackage.get.html.ftl +++ b/config/alfresco/templates/webscripts/org/alfresco/indexpackage.get.html.ftl @@ -52,7 +52,7 @@ Format Style:${desc.formatStyle} Default Format:${desc.defaultFormat!"Determined at run-time"} - Id:${desc.id} + Id:${desc.id} Description:${desc.storePath}/${desc.descPath}
diff --git a/config/alfresco/templates/webscripts/org/alfresco/indexuri.get.html.ftl b/config/alfresco/templates/webscripts/org/alfresco/indexuri.get.html.ftl index 481e1bb85f..c8d20c0a53 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/indexuri.get.html.ftl +++ b/config/alfresco/templates/webscripts/org/alfresco/indexuri.get.html.ftl @@ -52,7 +52,7 @@ Format Style:${desc.formatStyle} Default Format:${desc.defaultFormat!"Determined at run-time"} - Id:${desc.id} + Id:${desc.id} Description:${desc.storePath}/${desc.descPath}
diff --git a/config/alfresco/templates/webscripts/org/alfresco/scriptdump.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/scriptdump.get.desc.xml new file mode 100644 index 0000000000..c7924671dd --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/scriptdump.get.desc.xml @@ -0,0 +1,7 @@ + + Display Web Script + Full inspection of Web Script implementation - useful for diagnostics and download/upload + /script/{serviceId} + argument + admin + \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/scriptdump.get.html.ftl b/config/alfresco/templates/webscripts/org/alfresco/scriptdump.get.html.ftl new file mode 100644 index 0000000000..804a92aabb --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/scriptdump.get.html.ftl @@ -0,0 +1,61 @@ + + + + + Web Script: ${script.id} + + + + + + + +
Web Script: ${script.id}
Alfresco ${server.edition} v${server.version}
Generated from ${url.full} on ${date?datetime}
+

+ + Script Properties + + + + + + + <#list script.URIs as URI> + + + + + +
Id:${script.id}
Short Name:${script.shortName}
Description:${script.description}
Authentication:${script.requiredAuthentication}
Transaction:${script.requiredTransaction}
Method:${script.method}
URL Template:${URI}
Format Style:${script.formatStyle}
Default Format:${script.defaultFormat}
Implementation:${script_class}
+

+ <#list stores as store> + Store: ${store.path} +

+ + <#if store.files?size == 0> + + <#else> +

+ <#list store.files as file> +

+ + + +
[No implementation files]
File: ${file.path} <#if file.overridden>[overridden]
${file.content?html}
+

+ + + + + + <#list stores as store> + <#list store.files as file> + + + + + + + + + \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/scriptinstall.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/scriptinstall.get.desc.xml new file mode 100644 index 0000000000..164ceedf00 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/scriptinstall.get.desc.xml @@ -0,0 +1,6 @@ + + Web Script Installer Form + Web Script Installer Form + /installer + admin + \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/scriptinstall.get.html.ftl b/config/alfresco/templates/webscripts/org/alfresco/scriptinstall.get.html.ftl new file mode 100644 index 0000000000..07cdd57522 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/scriptinstall.get.html.ftl @@ -0,0 +1,33 @@ + + + + + Web Script Installer + + + + + + + + +
AlfrescoWeb Scripts Installer
Alfresco ${server.edition} v${server.version} +

+

+
Web Script: +
+
  +
+ +
  +
  +
To create a Web Script file that can be installed: +
  +
1) Display the full definition of the Web Script via the URL ${url.serviceContext}/script/{scriptid} +
  +
     e.g. to display the "AVM Browse Sample", issue ${url.serviceContext}/script/org/alfresco/sample/avmbrowse.get +
  +
2) Save the the HTML page displayed in step 1 +
+ + diff --git a/config/alfresco/templates/webscripts/org/alfresco/scriptinstall.post.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/scriptinstall.post.desc.xml new file mode 100644 index 0000000000..efbbe293d1 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/scriptinstall.post.desc.xml @@ -0,0 +1,6 @@ + + Install Web Script + Install Web Script + /installer + admin + \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/scriptinstall.post.html.ftl b/config/alfresco/templates/webscripts/org/alfresco/scriptinstall.post.html.ftl new file mode 100644 index 0000000000..bb6ba5ccb0 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/scriptinstall.post.html.ftl @@ -0,0 +1,42 @@ + + + + + Installed Web Script: ${installedScript.id} + + + + +
AlfrescoInstalled Web Script: ${installedScript.id} +
Alfresco ${server.edition} v${server.version} +
${date?datetime} +
+

+ +
Inspect ${installedScript.id} +
Back to Web Scripts Home +
+

+ + Script Properties + + + + + + + <#list installedScript.URIs as URI> + + + + +
Id:${installedScript.id}
Short Name:${installedScript.shortName}
Description:${installedScript.description}
Authentication:${installedScript.requiredAuthentication}
Transaction:${installedScript.requiredTransaction}
Method:${installedScript.method}
URL Template:${URI}
Format Style:${installedScript.formatStyle}
Default Format:${installedScript.defaultFormat}
+

+ + Files Installed + <#list installedFiles as file> +
${file.path}(store: ${file.store}) + +
+ + \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/status.ftl b/config/alfresco/templates/webscripts/status.ftl index 0a03ac5b71..fd233e2404 100644 --- a/config/alfresco/templates/webscripts/status.ftl +++ b/config/alfresco/templates/webscripts/status.ftl @@ -27,6 +27,10 @@ Server:Alfresco ${server.edition} v${server.version} schema ${server.schema} Time:${date?datetime} +   + <#if webscript?exists> + Diagnostics:Inspect Web Script (${webscript.id}) + diff --git a/config/alfresco/web-scripts-application-context.xml b/config/alfresco/web-scripts-application-context.xml index cba9841713..7742570ada 100644 --- a/config/alfresco/web-scripts-application-context.xml +++ b/config/alfresco/web-scripts-application-context.xml @@ -12,6 +12,7 @@ + @@ -199,6 +200,16 @@ + + + + + + + + + + diff --git a/source/java/org/alfresco/web/scripts/AbstractWebScript.java b/source/java/org/alfresco/web/scripts/AbstractWebScript.java index 24a63117e4..127780447d 100644 --- a/source/java/org/alfresco/web/scripts/AbstractWebScript.java +++ b/source/java/org/alfresco/web/scripts/AbstractWebScript.java @@ -131,7 +131,6 @@ public abstract class AbstractWebScript implements WebScript } } - /* (non-Javadoc) * @see org.alfresco.web.scripts.WebScript#getDescription() */ @@ -185,7 +184,6 @@ public abstract class AbstractWebScript implements WebScript return this.descriptorService; } - // // Scripting Support // @@ -299,6 +297,7 @@ public abstract class AbstractWebScript implements WebScript model.put("args", createArgModel(req)); model.put("guest", req.isGuest()); model.put("url", new URLModel(req)); + model.put("webscript", getDescription()); model.put("server", new ServerModel(descriptorService.getServerDescriptor())); // add template support diff --git a/source/java/org/alfresco/web/scripts/ClassPathStore.java b/source/java/org/alfresco/web/scripts/ClassPathStore.java index d1a4da5ad9..a254a2b5f0 100644 --- a/source/java/org/alfresco/web/scripts/ClassPathStore.java +++ b/source/java/org/alfresco/web/scripts/ClassPathStore.java @@ -27,9 +27,12 @@ package org.alfresco.web.scripts; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintWriter; import java.io.Reader; import java.util.ArrayList; import java.util.List; @@ -146,20 +149,92 @@ public class ClassPathStore implements WebScriptStore, InitializingBean return paths; } + /* (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptStore#getScriptDocumentPaths(org.alfresco.web.scripts.WebScript) + */ + public String[] getScriptDocumentPaths(WebScript script) + { + String[] paths; + + try + { + int filePathLength = fileDir.getAbsolutePath().length() +1; + List documentPaths = new ArrayList(); + String scriptPaths = script.getDescription().getId() + ".*"; + Resource[] resources = resolver.getResources("classpath*:" + classPath + "/" + scriptPaths); + for (Resource resource : resources) + { + if (resource instanceof FileSystemResource) + { + String documentPath = resource.getFile().getAbsolutePath().substring(filePathLength); + documentPath = documentPath.replace('\\', '/'); + documentPaths.add(documentPath); + } + } + paths = documentPaths.toArray(new String[documentPaths.size()]); + } + catch(IOException e) + { + // Note: Ignore: no service description documents found + paths = new String[0]; + } + + return paths; + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptStore#hasDocument(java.lang.String) + */ + public boolean hasDocument(String documentPath) + { + File document = new File(fileDir, documentPath); + return document.exists(); + } + /* (non-Javadoc) * @see org.alfresco.web.scripts.WebScriptStore#getDescriptionDocument(java.lang.String) */ - public InputStream getDescriptionDocument(String documentPath) + public InputStream getDocument(String documentPath) throws IOException { File document = new File(fileDir, documentPath); if (!document.exists()) { - throw new IOException("Description document " + documentPath + " does not exist."); + throw new IOException("Document " + documentPath + " does not exist within store " + getBasePath()); } return new FileInputStream(document); } + /* (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptStore#createDocument(java.lang.String, java.lang.String) + */ + public void createDocument(String documentPath, String content) throws IOException + { + File document = new File(fileDir, documentPath); + + // create directory + File path = document.getParentFile(); + path.mkdirs(); + + // create file + if (!document.createNewFile()) + { + throw new IOException("Document " + documentPath + " already exists"); + } + OutputStream output = new FileOutputStream(document); + try + { + PrintWriter writer = new PrintWriter(output); + writer.write(content); + writer.flush(); + } + finally + { + output.flush(); + output.close(); + } + } + /* (non-Javadoc) * @see org.alfresco.web.scripts.WebScriptStore#getTemplateLoader() */ diff --git a/source/java/org/alfresco/web/scripts/DeclarativeWebScriptRegistry.java b/source/java/org/alfresco/web/scripts/DeclarativeWebScriptRegistry.java index f616481260..a9baeae517 100644 --- a/source/java/org/alfresco/web/scripts/DeclarativeWebScriptRegistry.java +++ b/source/java/org/alfresco/web/scripts/DeclarativeWebScriptRegistry.java @@ -215,7 +215,7 @@ public class DeclarativeWebScriptRegistry extends AbstractLifecycleBean InputStream serviceDescIS = null; try { - serviceDescIS = apiStore.getDescriptionDocument(serviceDescPath); + serviceDescIS = apiStore.getDocument(serviceDescPath); serviceDesc = createDescription(apiStore, serviceDescPath, serviceDescIS); } catch(IOException e) diff --git a/source/java/org/alfresco/web/scripts/RepoStore.java b/source/java/org/alfresco/web/scripts/RepoStore.java index 094e0ffdc3..9794a22aec 100644 --- a/source/java/org/alfresco/web/scripts/RepoStore.java +++ b/source/java/org/alfresco/web/scripts/RepoStore.java @@ -24,11 +24,15 @@ */ package org.alfresco.web.scripts; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintWriter; import java.io.Reader; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.StringTokenizer; @@ -36,8 +40,11 @@ import org.alfresco.model.ContentModel; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.ScriptLocation; @@ -74,6 +81,7 @@ public class RepoStore implements WebScriptStore, ApplicationContextAware, Appli protected SearchService searchService; protected NodeService nodeService; protected ContentService contentService; + protected FileFolderService fileService; protected NamespaceService namespaceService; @@ -109,6 +117,14 @@ public class RepoStore implements WebScriptStore, ApplicationContextAware, Appli this.contentService = contentService; } + /** + * Sets the file service + */ + public void setFileFolderService(FileFolderService fileService) + { + this.fileService = fileService; + } + /** * Sets the namespace service */ @@ -258,6 +274,49 @@ public class RepoStore implements WebScriptStore, ApplicationContextAware, Appli return (nodes.size() == 1) ? nodes.get(0) : null; } + /* (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptStore#getScriptDocumentPaths(org.alfresco.web.scripts.WebScript) + */ + public String[] getScriptDocumentPaths(final WebScript script) + { + return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork() + { + public String[] doWork() throws Exception + { + return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback() + { + public String[] execute() throws Exception + { + int baseDirLength = baseDir.length() +1; + List documentPaths = new ArrayList(); + String scriptPath = script.getDescription().getScriptPath(); + NodeRef scriptNodeRef = findNodeRef(scriptPath); + if (scriptNodeRef != null) + { + org.alfresco.service.cmr.repository.Path repoScriptPath = nodeService.getPath(scriptNodeRef); + String id = script.getDescription().getId().substring(script.getDescription().getScriptPath().length() +1); + String query = "+PATH:\"" + repoScriptPath.toPrefixString(namespaceService) + "/*" + "\" +@cm\\:name:\"" + id + "\""; + ResultSet resultSet = searchService.query(repoStore, SearchService.LANGUAGE_LUCENE, query); + List nodes = resultSet.getNodeRefs(); + for (NodeRef nodeRef : nodes) + { + String name = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_NAME); + if (name.startsWith(id)) + { + String nodeDir = getPath(nodeRef); + String documentPath = nodeDir.substring(baseDirLength); + documentPaths.add(documentPath); + } + } + } + + return documentPaths.toArray(new String[documentPaths.size()]); + } + }); + } + }, AuthenticationUtil.getSystemUserName()); + } + /* (non-Javadoc) * @see org.alfresco.web.scripts.WebScriptStore#getDescriptionDocumentPaths() */ @@ -274,7 +333,7 @@ public class RepoStore implements WebScriptStore, ApplicationContextAware, Appli int baseDirLength = baseDir.length() +1; List documentPaths = new ArrayList(); - String query = "PATH:\"" + repoPath + "//*\" AND @cm\\:name:\"*desc.xml\""; + String query = "+PATH:\"" + repoPath + "//*\" AND +@cm\\:name:\"desc.xml\""; ResultSet resultSet = searchService.query(repoStore, SearchService.LANGUAGE_LUCENE, query); List nodes = resultSet.getNodeRefs(); for (NodeRef nodeRef : nodes) @@ -294,10 +353,31 @@ public class RepoStore implements WebScriptStore, ApplicationContextAware, Appli }, AuthenticationUtil.getSystemUserName()); } + /* (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptStore#hasDocument(java.lang.String) + */ + public boolean hasDocument(final String documentPath) + { + return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork() + { + public Boolean doWork() throws Exception + { + return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback() + { + public Boolean execute() throws Exception + { + NodeRef nodeRef = findNodeRef(documentPath); + return (nodeRef != null); + } + }); + } + }, AuthenticationUtil.getSystemUserName()); + } + /* (non-Javadoc) * @see org.alfresco.web.scripts.WebScriptStore#getDescriptionDocument(java.lang.String) */ - public InputStream getDescriptionDocument(final String documentPath) + public InputStream getDocument(final String documentPath) throws IOException { return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork() @@ -311,7 +391,7 @@ public class RepoStore implements WebScriptStore, ApplicationContextAware, Appli NodeRef nodeRef = findNodeRef(documentPath); if (nodeRef == null) { - throw new IOException("Description document " + documentPath + " does not exist."); + throw new IOException("Document " + documentPath + " does not exist."); } ContentReader reader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT); return reader.getContentInputStream(); @@ -321,6 +401,30 @@ public class RepoStore implements WebScriptStore, ApplicationContextAware, Appli }, AuthenticationUtil.getSystemUserName()); } + /* (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptStore#createDocument(java.lang.String, java.lang.String) + */ + public void createDocument(String documentPath, String content) throws IOException + { + String[] pathElements = documentPath.split("/"); + String[] folderElements = new String[pathElements.length -1]; + System.arraycopy(pathElements, 0, folderElements, 0, pathElements.length -1); + List folderElementsList = Arrays.asList(folderElements); + + // create folder + FileInfo pathInfo = fileService.makeFolders(baseNodeRef, folderElementsList, ContentModel.TYPE_FOLDER); + + // create file + String fileName = pathElements[pathElements.length -1]; + if (fileService.searchSimple(pathInfo.getNodeRef(), fileName) != null) + { + throw new IOException("Document " + documentPath + " already exists"); + } + FileInfo fileInfo = fileService.create(pathInfo.getNodeRef(), fileName, ContentModel.TYPE_CONTENT); + ContentWriter writer = fileService.getWriter(fileInfo.getNodeRef()); + writer.putContent(content); + } + /* (non-Javadoc) * @see org.alfresco.web.scripts.WebScriptStore#getTemplateLoader() */ diff --git a/source/java/org/alfresco/web/scripts/TestWebScriptServer.java b/source/java/org/alfresco/web/scripts/TestWebScriptServer.java index 36348e5539..62e609fc5d 100644 --- a/source/java/org/alfresco/web/scripts/TestWebScriptServer.java +++ b/source/java/org/alfresco/web/scripts/TestWebScriptServer.java @@ -46,7 +46,6 @@ import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.security.AuthenticationService; -import org.alfresco.service.cmr.security.AuthorityService; import org.alfresco.web.config.ServerConfigElement; import org.springframework.context.ApplicationContext; import org.springframework.context.MessageSource; diff --git a/source/java/org/alfresco/web/scripts/WebScriptDescriptionImpl.java b/source/java/org/alfresco/web/scripts/WebScriptDescriptionImpl.java index 09b93f13c5..447c5d3ffe 100644 --- a/source/java/org/alfresco/web/scripts/WebScriptDescriptionImpl.java +++ b/source/java/org/alfresco/web/scripts/WebScriptDescriptionImpl.java @@ -109,7 +109,7 @@ public class WebScriptDescriptionImpl implements WebScriptDescription public InputStream getDescDocument() throws IOException { - return store.getDescriptionDocument(descPath); + return store.getDocument(descPath); } /** diff --git a/source/java/org/alfresco/web/scripts/WebScriptStorage.java b/source/java/org/alfresco/web/scripts/WebScriptStorage.java index 40afcabd79..8288ad7200 100644 --- a/source/java/org/alfresco/web/scripts/WebScriptStorage.java +++ b/source/java/org/alfresco/web/scripts/WebScriptStorage.java @@ -109,6 +109,25 @@ public class WebScriptStorage implements ApplicationContextAware, ApplicationLis return stores; } + /** + * Gets the Web Script Store for the given Store path + * + * @param storePath + * @return store (or null, if not found) + */ + public WebScriptStore getStore(String storePath) + { + Collection stores = getStores(); + for (WebScriptStore store : stores) + { + if (store.getBasePath().equals(storePath)) + { + return store; + } + } + return null; + } + /** * Gets the Template Processor * diff --git a/source/java/org/alfresco/web/scripts/WebScriptStore.java b/source/java/org/alfresco/web/scripts/WebScriptStore.java index 09aa3a38f3..6d236af9b5 100644 --- a/source/java/org/alfresco/web/scripts/WebScriptStore.java +++ b/source/java/org/alfresco/web/scripts/WebScriptStore.java @@ -59,16 +59,43 @@ public interface WebScriptStore public String[] getDescriptionDocumentPaths(); /** - * Gets a description document + * Gets the paths of all implementation files for a given Web Script * - * @param documentPath description document path - * @return input stream onto description document + * @param script web script + * @return array of implementation document paths + */ + public String[] getScriptDocumentPaths(WebScript script); + + /** + * Determines if the document exists + * + * @param documentPath document path + * @return true => exists, false => does not exist + */ + public boolean hasDocument(String documentPath); + + /** + * Gets a document + * + * @param documentPath document path + * @return input stream onto document * * @throws IOException */ - public InputStream getDescriptionDocument(String documentPath) + public InputStream getDocument(String documentPath) throws IOException; - + + /** + * Creates a document + * + * @param documentPath + * @param content + * + * @throws IOException + */ + public void createDocument(String documentPath, String content) + throws IOException; + /** * Gets the template loader for this store * diff --git a/source/java/org/alfresco/web/scripts/bean/ServiceDump.java b/source/java/org/alfresco/web/scripts/bean/ServiceDump.java new file mode 100644 index 0000000000..f5cc5dd847 --- /dev/null +++ b/source/java/org/alfresco/web/scripts/bean/ServiceDump.java @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.web.scripts.bean; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.alfresco.web.scripts.DeclarativeWebScript; +import org.alfresco.web.scripts.WebScript; +import org.alfresco.web.scripts.WebScriptException; +import org.alfresco.web.scripts.WebScriptRequest; +import org.alfresco.web.scripts.WebScriptStatus; +import org.alfresco.web.scripts.WebScriptStorage; +import org.alfresco.web.scripts.WebScriptStore; + + +/** + * Dumps everything known about the specified Web Script + * + * @author davidc + */ +public class ServiceDump extends DeclarativeWebScript +{ + private WebScriptStorage storage; + + + public void setStorage(WebScriptStorage storage) + { + this.storage = storage; + } + + + @Override + protected Map executeImpl(WebScriptRequest req, WebScriptStatus status) + { + // extract web script id + String scriptId = req.getExtensionPath(); + if (scriptId == null || scriptId.length() == 0) + { + throw new WebScriptException("Web Script Id not provided"); + } + + // locate web script + WebScript script = getWebScriptRegistry().getWebScript(scriptId); + if (script == null) + { + throw new WebScriptException("Web Script Id '" + scriptId + "' not found"); + } + + // construct model + Map model = new HashMap(7, 1.0f); + Map implPaths = new HashMap(); + List modelStores = new ArrayList(); + model.put("script", script.getDescription()); + model.put("script_class", script.getClass().toString()); + model.put("stores", modelStores); + + // locate web script stores + Collection stores = storage.getStores(); + for (WebScriptStore store : stores) + { + Store modelStore = new Store(); + modelStore.path = store.getBasePath(); + + // locate script implementation files + String[] scriptPaths = store.getScriptDocumentPaths(script); + for (String scriptPath : scriptPaths) + { + Implementation impl = new Implementation(); + impl.path = scriptPath; + impl.overridden = implPaths.containsKey(scriptPath); + + // extract implementation content + InputStream documentIS = null; + try + { + documentIS = store.getDocument(scriptPath); + InputStreamReader isReader = new InputStreamReader(documentIS); + StringWriter stringWriter = new StringWriter(); + char[] buffer = new char[2048]; + int read = isReader.read(buffer); + while (read != -1) + { + stringWriter.write(buffer, 0, read); + read = isReader.read(buffer); + } + impl.content = stringWriter.toString(); + } + catch(IOException e) + { + impl.throwable = e; + } + finally + { + try + { + if (documentIS != null) documentIS.close(); + } + catch(IOException e) + { + // NOTE: ignore close exception + } + } + + // record web script implementation file against store + modelStore.files.add(impl); + } + + // record store in list of stores + modelStores.add(modelStore); + } + + return model; + } + + + public static class Store + { + private String path; + private Collection files = new ArrayList(); + + public String getPath() + { + return path; + } + + public Collection getFiles() + { + return files; + } + + } + + public static class Implementation + { + private String path; + private boolean overridden; + private String content; + private Exception throwable; + + public String getPath() + { + return path; + } + + public String getContent() + { + return content; + } + + public boolean getOverridden() + { + return overridden; + } + + public Throwable getException() + { + return throwable; + } + } + +} + \ No newline at end of file diff --git a/source/java/org/alfresco/web/scripts/bean/ServiceInstall.java b/source/java/org/alfresco/web/scripts/bean/ServiceInstall.java new file mode 100644 index 0000000000..4f3fc2c0bc --- /dev/null +++ b/source/java/org/alfresco/web/scripts/bean/ServiceInstall.java @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.web.scripts.bean; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.alfresco.web.scripts.DeclarativeWebScript; +import org.alfresco.web.scripts.WebScript; +import org.alfresco.web.scripts.WebScriptDescription; +import org.alfresco.web.scripts.WebScriptException; +import org.alfresco.web.scripts.WebScriptRegistry; +import org.alfresco.web.scripts.WebScriptRequest; +import org.alfresco.web.scripts.WebScriptServletRequest; +import org.alfresco.web.scripts.WebScriptStatus; +import org.alfresco.web.scripts.WebScriptStorage; +import org.alfresco.web.scripts.WebScriptStore; +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.fileupload.FileItemFactory; +import org.apache.commons.fileupload.FileUploadException; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.XPath; +import org.dom4j.io.SAXReader; + + +/** + * Install a Web Script + * + * @author davidc + */ +public class ServiceInstall extends DeclarativeWebScript +{ + private WebScriptStorage storage; + + + public void setStorage(WebScriptStorage storage) + { + this.storage = storage; + } + + + @Override + protected Map executeImpl(WebScriptRequest req, WebScriptStatus status) + { + if (!(req instanceof WebScriptServletRequest)) + { + throw new WebScriptException("Web Script install only supported via HTTP Servlet"); + } + HttpServletRequest servletReq = ((WebScriptServletRequest)req).getHttpServletRequest(); + + // construct model + Map model = new HashMap(7, 1.0f); + List installedFiles = new ArrayList(); + model.put("installedFiles", installedFiles); + + try + { + // extract uploaded file + FileItemFactory factory = new DiskFileItemFactory(); + ServletFileUpload upload = new ServletFileUpload(factory); + boolean isMultipart = upload.isMultipartContent(servletReq); + if (!isMultipart) + { + throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Web Script install request is not multi-part"); + } + FileItem part = null; + List files = upload.parseRequest(servletReq); + for (FileItem file : files) + { + if (!file.isFormField()) + { + if (part != null) + { + throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Web Script install request expects only one file upload"); + } + part = file; + } + } + + // find web script definition + Document document = null; + InputStream fileIS = part.getInputStream(); + try + { + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileIS)); + SAXReader reader = new SAXReader(); + document = reader.read(bufferedReader); + } + finally + { + fileIS.close(); + } + Element rootElement = document.getRootElement(); + XPath xpath = rootElement.createXPath("//ws:webscript"); + Map uris = new HashMap(); + uris.put("ws", "http://www.alfresco.org/webscript/1.0"); + xpath.setNamespaceURIs(uris); + List nodes = xpath.selectNodes(rootElement); + if (nodes.size() == 0) + { + throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Cannot locate Web Script in uploaded file"); + } + + // extract web script definition + Element webscriptElem = (Element)nodes.get(0); + String scriptId = webscriptElem.attributeValue("scriptid"); + if (scriptId == null || scriptId.length() == 0) + { + throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Expected scriptid value on webscript element"); + } + Iterator iter = webscriptElem.elementIterator(); + while (iter.hasNext()) + { + Element fileElem = (Element)iter.next(); + String webscriptStore = fileElem.attributeValue("store"); + if (webscriptStore == null || webscriptStore.length() == 0) + { + throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Expected store value on webscript element"); + } + String webscriptPath = fileElem.attributeValue("path"); + if (webscriptPath == null || webscriptPath.length() == 0) + { + throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Expected file value on webscript element"); + } + String webscriptContent = fileElem.getText(); + + // install web script implementation file + installFile(webscriptStore, webscriptPath, webscriptContent); + InstalledFile installedFile = new InstalledFile(); + installedFile.store = webscriptStore; + installedFile.path = webscriptPath; + installedFiles.add(installedFile); + } + + // reset the web script registry + WebScriptRegistry registry = getWebScriptRegistry(); + registry.reset(); + + // locate installed web script + WebScript webscript = registry.getWebScript(scriptId); + if (webscript == null) + { + throw new WebScriptException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to install Web Script " + scriptId); + } + model.put("installedScript", webscript.getDescription()); + } + catch(FileUploadException e) + { + throw new WebScriptException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); + } + catch(DocumentException e) + { + throw new WebScriptException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); + } + catch(IOException e) + { + throw new WebScriptException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); + } + + return model; + } + + + private void installFile(String storePath, String file, String content) + { + // retrieve appropriate web script store + WebScriptStore store = storage.getStore(storePath); + if (store == null) + { + throw new WebScriptException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Store path " + storePath + " refers to a store that does not exist"); + } + + // determine if file already exists in store + if (store.hasDocument(file)) + { + throw new WebScriptException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Web Script file " + file + " already exists in store " + storePath); + } + + // create the web script file + try + { + store.createDocument(file, content); + } + catch(IOException e) + { + throw new WebScriptException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to install Web Script file " + file + " into store" + storePath); + } + } + + + public static class InstalledFile + { + private WebScriptDescription script; + private String store; + private String path; + + public String getStore() + { + return store; + } + + public String getPath() + { + return path; + } + } + +} + \ No newline at end of file