View Javadoc

1   /**
2    * Copyright (C) 2005-2009 Alfresco Software Limited.
3    *
4    * This file is part of the Spring Surf Extension project.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *  http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.springframework.roo.addon.surf.template;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.util.Hashtable;
25  import java.util.Scanner;
26  import java.util.SortedSet;
27  import java.util.TreeSet;
28  import java.util.logging.Logger;
29  
30  import org.springframework.roo.addon.surf.Constants;
31  import org.springframework.roo.addon.surf.SurfOperations;
32  import org.springframework.roo.addon.surf.region.RegionConfig;
33  import org.springframework.roo.addon.surf.util.SurfUtils;
34  import org.springframework.roo.file.monitor.event.FileDetails;
35  import org.springframework.roo.metadata.MetadataService;
36  import org.springframework.roo.process.manager.FileManager;
37  import org.springframework.roo.process.manager.MutableFile;
38  import org.springframework.roo.project.Path;
39  import org.springframework.roo.project.PathResolver;
40  import org.springframework.roo.project.ProjectOperations;
41  import org.springframework.roo.support.lifecycle.ScopeDevelopment;
42  import org.springframework.roo.support.util.Assert;
43  import org.springframework.roo.support.util.FileCopyUtils;
44  import org.springframework.roo.support.util.TemplateUtils;
45  import org.springframework.roo.support.util.XmlUtils;
46  import org.w3c.dom.Document;
47  import org.w3c.dom.Element;
48  
49  /**
50   * Provides Surf Template operations.
51   *
52   * @author Yong Qu
53   * @since 1.0
54   */
55  @ScopeDevelopment
56  public class TemplateOperations {
57  
58  	Logger logger = Logger.getLogger(TemplateOperations.class.getName());
59  
60  	private FileManager fileManager;
61  	private PathResolver pathResolver;
62  
63  	private SurfOperations surfOperations;
64  
65  	/**
66  	 * @param fileManager
67  	 * @param pathResolver
68  	 * @param metadataService
69  	 * @param projectOperations
70  	 */
71  	public TemplateOperations(FileManager fileManager, PathResolver pathResolver, MetadataService metadataService, ProjectOperations projectOperations) {
72  		Assert.notNull(fileManager, "File manager required");
73  		Assert.notNull(pathResolver, "Path resolver required");
74  		Assert.notNull(metadataService, "Metadata service required");
75  		Assert.notNull(projectOperations, "Project operations required");
76  
77  		this.fileManager = fileManager;
78  		this.pathResolver = pathResolver;
79  		this.surfOperations = new SurfOperations(fileManager, pathResolver, metadataService, projectOperations);
80  
81  	}
82  
83  	/**
84  	 * Checks if template related operations are available.
85  	 * @return true if template related operations are available.
86  	 */
87  	public boolean isTemplateOperationAvailable() {
88  		return surfOperations.isManageSurfAvailable();
89  	}
90  
91  	/**
92  	 * @param fileIdentifier
93  	 * @return
94  	 */
95  	public String getTemplatePath(FileDetails fileIdentifier) {
96  		String surfTemplatesRootPath = pathResolver.getRoot(Path.SRC_MAIN_WEBAPP) + "/" + Constants.SURF_TEMPLATE_CP;
97  		surfTemplatesRootPath = surfTemplatesRootPath.replace(String.valueOf(File.separatorChar),"/");
98  		String fullPath = fileIdentifier.getCanonicalPath().replace(String.valueOf(File.separatorChar),"/");
99  		int index = fullPath.indexOf(surfTemplatesRootPath);
100 		if (index == -1 ){
101 			surfTemplatesRootPath = pathResolver.getRoot(Path.SRC_MAIN_WEBAPP) + "/" + Constants.SURF_TEMPLATE_NEW_CP;
102 			surfTemplatesRootPath = surfTemplatesRootPath.replace(String.valueOf(File.separatorChar),"/");
103 			index = fullPath.indexOf(surfTemplatesRootPath);
104 		}
105 		if (index == -1){
106 			return null;
107 		} else {
108 			return fullPath.substring(index+surfTemplatesRootPath.length()).replace(".ftl", "");
109 		}
110 	}
111 
112 	/**
113 	 * @param path
114 	 * @return
115 	 */
116 	public FileDetails findSurfTemplateByPath(String path) {
117 		String surfTemplatesRootPath = pathResolver.getRoot(Path.SRC_MAIN_WEBAPP) + "/" + Constants.SURF_TEMPLATE_CP;
118 		String antPath = (surfTemplatesRootPath+path+".ftl").replace("/", File.separator);
119 		SortedSet<FileDetails> entries = fileManager.findMatchingAntPath(antPath);
120 		if (entries.size()==0 ){
121 			surfTemplatesRootPath = pathResolver.getRoot(Path.SRC_MAIN_WEBAPP) + "/" + Constants.SURF_TEMPLATE_NEW_CP;
122 			antPath = (surfTemplatesRootPath+path+".ftl").replace("/", File.separator);
123 			entries = fileManager.findMatchingAntPath(antPath);
124 		}
125 		if (entries.size()==0 ){
126 			return null;
127 		}else{
128 			return entries.first();
129 		}
130 	}
131 
132 	/**
133 	 * @return
134 	 */
135 	public SortedSet<String> listSurfTemplateNames() {
136 		SortedSet<String> templateList = new TreeSet<String>();
137 		for (FileDetails fileIdentifier : listSurfTemplateFiles()) {
138 			templateList.add(fileIdentifier.getFile().getName().replace(".ftl",""));
139 		}
140 		return templateList;
141 	}
142 
143 	/**
144 	 * @return
145 	 */
146 	public SortedSet<String> listSurfTemplatePaths() {
147 		SortedSet<String> templateList = new TreeSet<String>();
148 		for (FileDetails fileIdentifier : listSurfTemplateFiles()) {
149 			templateList.add(getTemplatePath(fileIdentifier));
150 		}
151 		return templateList;
152 	}
153 	
154 	/**
155 	 * Returns list of all available templates.
156 	 * @return List of templates.
157 	 */
158 	public SortedSet<FileDetails> listSurfTemplateFiles() {
159 
160 		String surfTemplatesRootPath = pathResolver.getRoot(Path.SRC_MAIN_WEBAPP) + "/" + Constants.SURF_TEMPLATE_CP;
161 		String antPath = (surfTemplatesRootPath+"**/*.ftl").replace("/", File.separator);
162 		SortedSet<FileDetails> entries = fileManager.findMatchingAntPath(antPath);
163 		SortedSet<FileDetails> templateList = new TreeSet<FileDetails>();
164 
165 		String keyword = "<@region.*/>";
166 
167 		for (FileDetails fileIdentifier : entries) {
168 			InputStream templateFileInputStream = fileManager.getInputStream(fileIdentifier.getCanonicalPath());
169 			if ( SurfUtils.fileContainsString(templateFileInputStream, keyword) ) {
170 				templateList.add(fileIdentifier);
171 			}
172 		}
173 
174 		//Look at the WEB-INF/templates as well.
175 		surfTemplatesRootPath = pathResolver.getRoot(Path.SRC_MAIN_WEBAPP) + "/" + Constants.SURF_TEMPLATE_NEW_CP;
176 		antPath = (surfTemplatesRootPath+"**/*.ftl").replace("/", File.separator);
177 		entries = fileManager.findMatchingAntPath(antPath);
178 
179 		for (FileDetails fileIdentifier : entries) {
180 			InputStream templateFileInputStream = fileManager.getInputStream(fileIdentifier.getCanonicalPath());
181 			if ( SurfUtils.fileContainsString(templateFileInputStream, keyword) ) {
182 				templateList.add(fileIdentifier);
183 			}
184 		}
185 
186 		return templateList;
187 	}
188 	
189 	/**
190 	 * Returns list of all available templates.
191 	 * @return List of templates.
192 	 */
193 	public SortedSet<String> listSurfTemplates() {
194 
195 		String surfTemplatesRootPath = pathResolver.getRoot(Path.SRC_MAIN_WEBAPP) + "/" + Constants.SURF_TEMPLATE_CP;
196 		String antPath = surfTemplatesRootPath+"**/*.ftl";
197 		int surfTemplatesRootPathLength = surfTemplatesRootPath.length();
198 
199 		antPath = antPath.replace("/", File.separator);
200 		SortedSet<FileDetails> entries = fileManager.findMatchingAntPath(antPath);
201 		SortedSet<String> templateList = new TreeSet<String>();
202 
203 		for (FileDetails fileIdentifier : entries) {
204 
205 			InputStream templateFileInputStream = fileManager.getInputStream(fileIdentifier.getCanonicalPath());
206 			Scanner templateScanner = new Scanner(templateFileInputStream);
207 			String matchStr= templateScanner.findWithinHorizon("<@region.*/>", 0);
208 
209 			if ( matchStr != null ) {
210 				templateScanner.close();
211 
212 				String filePath = fileIdentifier.getCanonicalPath().substring(surfTemplatesRootPathLength).replace(String.valueOf(File.separatorChar),"/").replace(".ftl","");
213 				templateList.add(filePath);
214 			}
215 		}
216 
217 		//Look at the WEB-INF/templates as well.
218 		surfTemplatesRootPath = pathResolver.getRoot(Path.SRC_MAIN_WEBAPP) + "/" + Constants.SURF_TEMPLATE_NEW_CP;
219 		antPath = surfTemplatesRootPath+"**/*.ftl";
220 		surfTemplatesRootPathLength = surfTemplatesRootPath.length();
221 
222 		antPath = antPath.replace("/", File.separator);
223 		entries = fileManager.findMatchingAntPath(antPath);
224 
225 		for (FileDetails fileIdentifier : entries) {
226 
227 			InputStream templateFileInputStream = fileManager.getInputStream(fileIdentifier.getCanonicalPath());
228 			Scanner templateScanner = new Scanner(templateFileInputStream);
229 			String matchStr= templateScanner.findWithinHorizon("<@region.*/>", 0);
230 
231 			if ( matchStr != null ) {
232 				templateScanner.close();
233 
234 				String filePath = fileIdentifier.getCanonicalPath().substring(surfTemplatesRootPathLength).replace(String.valueOf(File.separatorChar),"/").replace(".ftl","");
235 				templateList.add(filePath);
236 			}
237 		}
238 
239 		return templateList;
240 	}
241 
242 	/**
243 	 * Checks if the template exists.
244 	 * @param templatePath Template path.
245 	 * @return True if the template exists. False if it doesn't.
246 	 */
247 	public boolean isSurfTemplateInstanceAvailable(String templatePath) {
248 
249 		SortedSet<String> templateList = listSurfTemplateInstances();
250 		return templateList.contains(templatePath);
251 	}
252 
253 	/**
254 	 * Checks if the template exists.
255 	 * @param templatePath Template path.
256 	 * @return True if the template exists. False if it doesn't.
257 	 */
258 	public boolean isSurfTemplateAvailable(String templatePath) {
259 
260 		SortedSet<String> templateList = listSurfTemplates();
261 		return templateList.contains(templatePath);
262 	}
263 
264 	public FileDetails findSurfTemplateInstanceByName(String name) {
265 
266 		String surfTemplatesRootPath = pathResolver.getRoot(Path.SRC_MAIN_WEBAPP) + "/"+Constants.WEB_INF;
267 		String antPath = surfTemplatesRootPath+"**/"+name+".xml";
268 		antPath = antPath.replace("/", File.separator);
269 		SortedSet<FileDetails> entries = fileManager.findMatchingAntPath(antPath);
270 		for (FileDetails fileIdentifier : entries) {
271 			if ( SurfUtils.checkSurfXMLType(fileManager, fileIdentifier.getCanonicalPath(),"template-instance") ) {
272 				return fileIdentifier;
273 			}
274 		}
275 		return null;
276 	}
277 	/**
278 	 * Returns list of all available template instances.
279 	 * @return List of template instances.
280 	 */
281 	public SortedSet<String> listSurfTemplateInstances() {
282 
283 		String surfTemplatesRootPath = pathResolver.getRoot(Path.SRC_MAIN_WEBAPP) + "/"+Constants.WEB_INF;
284 		String antPath = surfTemplatesRootPath+"**/*.xml";
285 		antPath = antPath.replace("/", File.separator);
286 		SortedSet<FileDetails> entries = fileManager.findMatchingAntPath(antPath);
287 		SortedSet<String> templateInstanceList = new TreeSet<String>();
288 
289 		for (FileDetails fileIdentifier : entries) {
290 			if ( SurfUtils.checkSurfXMLType(fileManager, fileIdentifier.getCanonicalPath(),"template-instance") ) {
291 				templateInstanceList.add(fileIdentifier.getFile().getName().replace(".xml",""));
292 			}
293 		}
294 
295 		return templateInstanceList;
296 	}
297 
298 	/**
299 	 * Returns configurations of all regions belongs to the template.
300 	 * @param templatePath Template path.
301 	 * @return List of template regions.
302 	 */
303 	public Hashtable<String,RegionConfig> listSurfTemplateRegions(String templatePath) {
304 		// Inspect the template and list all components.
305 		Hashtable<String,RegionConfig> templateRegionList = new Hashtable<String,RegionConfig>();
306 		FileDetails templateFile = findSurfTemplateByPath(templatePath);
307 
308 		if (templateFile==null){
309 			logger.warning("Template "+templatePath+" doesn't exist");
310 			return templateRegionList;
311 		}
312 
313 		InputStream templateFileInputStream = fileManager.getInputStream(templateFile.getCanonicalPath());
314 
315 		Scanner templateScanner = new Scanner(templateFileInputStream);
316 		String matchStr= templateScanner.findWithinHorizon("<@region.*/>", 0);
317 
318 		while ( matchStr != null ) {
319 			templateRegionList.put(getAttributeValue(matchStr,"id"),new RegionConfig(getAttributeValue(matchStr,"id"),getAttributeValue(matchStr,"scope")));
320 			matchStr = templateScanner.findWithinHorizon("<@region.*/>", 0);
321 		}
322 
323 		templateScanner.close();
324 		return templateRegionList;
325 	}
326 
327 	/**
328 	 * @param str
329 	 * @param attrName
330 	 * @return
331 	 */
332 	private String getAttributeValue(String str, String attrName) {
333 		Scanner attrScanner = new Scanner(str);
334 		String matchStr = attrScanner.findWithinHorizon(attrName+"\\s*?=\\s*?\".*?\"", str.length());
335 		Scanner strScanner = new Scanner(matchStr).useDelimiter("\"");
336 		strScanner .next();
337 		String attrVal = strScanner.next();
338 		attrScanner.close();
339 		strScanner.close();
340 		return attrVal;
341 	}
342 
343 	/**
344 	 * @param instanceName
345 	 * @return
346 	 */
347 	public String getTemplatePath(String instanceName) {
348 
349 		// Locate page template
350 		FileDetails templateInstanceXmlFile = this.findSurfTemplateInstanceByName(instanceName);
351 		if ( templateInstanceXmlFile == null){
352 			return "";
353 		}
354 
355 		InputStream templateInstanceInputStream = fileManager.getInputStream(templateInstanceXmlFile.getCanonicalPath());
356 		Document pom;
357 		try {
358 			pom = XmlUtils.getDocumentBuilder().parse(templateInstanceInputStream);
359 		} catch (Exception ex) {
360 			throw new IllegalStateException(ex);
361 		}
362 
363 		Element rootElement = (Element) pom.getFirstChild();
364 		String templatePath = XmlUtils.findFirstElementByName("template-type", rootElement).getTextContent();
365 
366 		try {
367 			templateInstanceInputStream.close();
368 		} catch (Exception ex) {
369 			throw new IllegalStateException(ex);
370 		}
371 
372 		return templatePath;
373 	}
374 
375 	/**
376 	 * Creates a new template.
377 	 * @param templatePath Template path.
378 	 * @return
379 	 */
380 	public boolean newTemplate(String templatePath) {
381 		Assert.hasText(templatePath,"Template path required.");
382 		templatePath = templatePath.replace("/", File.separator).replace("\\", File.separator);
383 		if ( findSurfTemplateByPath(templatePath) != null){
384 			logger.warning("Template "+templatePath+" exists.");
385 			return false;
386 		} else {
387 			MutableFile newTemplateFile = fileManager.createFile(pathResolver.getRoot(Path.SRC_MAIN_WEBAPP) + File.separator + Constants.SURF_TEMPLATE_NEW_CP+templatePath+".ftl");
388 			InputStream templateInputStream = TemplateUtils.getTemplate(getClass(), "template-template.ftl");
389 			try {
390 				FileCopyUtils.copy(templateInputStream, newTemplateFile.getOutputStream());
391 			} catch (IOException ex) {
392 				throw new IllegalStateException(ex);
393 			}
394 			fileManager.scan();
395 			return true;
396 		}
397 	}
398 	
399 	/**
400 	 * Creates a new template instance.
401 	 * @param id Template instance id.
402 	 * @param path Template instance path.
403 	 * @param templatePath Template path.
404 	 * @return true if a new template instance is created.
405 	 */
406 	public boolean newTemplateInstance(String id, String path, String templatePath) {
407 
408 		FileDetails templateInstanceXmlFile = this.findSurfTemplateInstanceByName(id);
409 		if ( templateInstanceXmlFile != null){
410 			logger.warning("Template instance "+id+" exists.");
411 			return false;
412 		}
413 		FileDetails templateFile = this.findSurfTemplateByPath(templatePath);
414 		if ( templateFile == null){
415 			logger.warning("Template "+templatePath+" doesn't exist.");
416 			return false;
417 		}
418 
419 		if (path==null) {
420 			path = Constants.SURF_TEMPLATE_DEFAULT_CP;
421 		} else {
422 			path = Constants.WEB_INF+path+File.separator;
423 		}
424 
425 		String templateInstanceXmlFilename = path+id+".xml";
426 
427 		InputStream templateInstanceInputStream = TemplateUtils.getTemplate(getClass(), "template-instance-template.xml");
428 		Document pom;
429 		try {
430 			pom = XmlUtils.getDocumentBuilder().parse(templateInstanceInputStream);
431 		} catch (Exception ex) {
432 			throw new IllegalStateException(ex);
433 		}
434 
435 		Element rootElement = (Element) pom.getFirstChild();
436 		XmlUtils.findFirstElementByName("template-type", rootElement).setTextContent(templatePath);
437 		XmlUtils.findFirstElementByName("title", rootElement).setTextContent(id);
438 		XmlUtils.findFirstElementByName("description", rootElement).setTextContent("Instance of "+templatePath);
439 
440 		MutableFile mutableFile = fileManager.createFile(pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, templateInstanceXmlFilename));
441 		XmlUtils.writeXml(mutableFile.getOutputStream(), pom);
442 
443 		fileManager.scan();
444 
445 		try {
446 			templateInstanceInputStream.close();
447 		} catch (Exception ex) {
448 			throw new IllegalStateException(ex);
449 		}
450 
451 		return true;
452 
453 	}
454 
455 	/**
456 	 * Returns list of template instances.
457 	 * @return List of template instances.
458 	 */
459 	public Hashtable <String,FileDetails> getSurfTemplateInstances() {
460 
461 		String antPath = (pathResolver.getRoot(Path.SRC_MAIN_WEBAPP) + "/"+Constants.WEB_INF + "**/*.xml").replace("/", File.separator);
462 
463 		SortedSet<FileDetails> entries = fileManager.findMatchingAntPath(antPath);
464 
465 		Hashtable <String,FileDetails> pageList = new Hashtable <String,FileDetails>();
466 
467 		for (FileDetails fileIdentifier : entries) {
468 			if ( SurfUtils.checkSurfXMLType(fileManager, fileIdentifier.getCanonicalPath(),"page") ) {
469 				String pageId = fileIdentifier.getFile().getName().replace(".xml","");
470 				pageList.put(pageId,fileIdentifier);
471 			}
472 		}
473 
474 		return pageList;
475 	}
476 
477 }