View Javadoc

1   /*
2    * Copyright 2004-2006 the Seasar Foundation and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.seasar.tuigwaa.cms;
17  
18  import java.io.File;
19  import java.io.IOException;
20  import java.io.InputStream;
21  import java.io.OutputStream;
22  import java.io.StringWriter;
23  import java.security.Principal;
24  import java.util.ArrayList;
25  import java.util.Collections;
26  import java.util.Comparator;
27  import java.util.Date;
28  import java.util.Enumeration;
29  import java.util.Hashtable;
30  import java.util.Iterator;
31  import java.util.List;
32  import java.util.Properties;
33  import java.util.Vector;
34  
35  import org.apache.commons.codec.digest.DigestUtils;
36  import org.apache.commons.io.CopyUtils;
37  import org.apache.commons.io.IOUtils;
38  import org.apache.slide.authenticate.CredentialsToken;
39  import org.apache.slide.authenticate.SecurityToken;
40  import org.apache.slide.common.Domain;
41  import org.apache.slide.common.NamespaceAccessToken;
42  import org.apache.slide.common.ServiceAccessException;
43  import org.apache.slide.common.SlideException;
44  import org.apache.slide.common.SlideToken;
45  import org.apache.slide.common.SlideTokenImpl;
46  import org.apache.slide.common.Uri;
47  import org.apache.slide.content.Content;
48  import org.apache.slide.content.NodeProperty;
49  import org.apache.slide.content.NodeRevisionContent;
50  import org.apache.slide.content.NodeRevisionDescriptor;
51  import org.apache.slide.content.NodeRevisionDescriptors;
52  import org.apache.slide.content.NodeRevisionNumber;
53  import org.apache.slide.content.RevisionContentNotFoundException;
54  import org.apache.slide.content.RevisionDescriptorNotFoundException;
55  import org.apache.slide.content.RevisionNotFoundException;
56  import org.apache.slide.event.VetoException;
57  import org.apache.slide.lock.ObjectLockedException;
58  import org.apache.slide.macro.CopyMacroException;
59  import org.apache.slide.macro.DeleteMacroException;
60  import org.apache.slide.macro.Macro;
61  import org.apache.slide.macro.MacroParameters;
62  import org.apache.slide.search.Search;
63  import org.apache.slide.search.SearchQuery;
64  import org.apache.slide.search.SearchQueryResult;
65  import org.apache.slide.search.basic.ComparableResource;
66  import org.apache.slide.security.AccessDeniedException;
67  import org.apache.slide.security.NodePermission;
68  import org.apache.slide.security.Security;
69  import org.apache.slide.store.ExtendedStore;
70  import org.apache.slide.store.Store;
71  import org.apache.slide.structure.ActionNode;
72  import org.apache.slide.structure.LinkNode;
73  import org.apache.slide.structure.LinkedObjectNotFoundException;
74  import org.apache.slide.structure.ObjectAlreadyExistsException;
75  import org.apache.slide.structure.ObjectNode;
76  import org.apache.slide.structure.ObjectNotFoundException;
77  import org.apache.slide.structure.Structure;
78  import org.apache.slide.structure.SubjectNode;
79  import org.seasar.framework.log.Logger;
80  import org.seasar.tuigwaa.cms.core.CmsConstants;
81  import org.seasar.tuigwaa.cms.core.Page;
82  import org.seasar.tuigwaa.cms.core.PageImpl;
83  import org.seasar.tuigwaa.cms.core.Resource;
84  import org.seasar.tuigwaa.cms.core.ResourceImpl;
85  import org.seasar.tuigwaa.security.SecurityService;
86  import org.seasar.tuigwaa.security.SecurityUtils;
87  import org.seasar.tuigwaa.system.TgwException;
88  import org.seasar.tuigwaa.system.TgwSecurityException;
89  import org.seasar.tuigwaa.util.MimeMappings;
90  import org.seasar.tuigwaa.util.TgwContext;
91  
92  import com.isenshi.util.CharUtil;
93  import com.isenshi.util.Diff;
94  import com.isenshi.util.ImageUtils;
95  import com.isenshi.util.PathUtils;
96  import com.isenshi.util.ResourceUtils;
97  import com.isenshi.util.extlib.SearchElement;
98  import com.isenshi.util.extlib.SlideRequiredInterceptor;
99  
100 /***
101  * @author nishioka
102  */
103 public class ContentsStoreServiceSlideImpl implements ContentsStoreService {
104 
105 	private static final String PAGE_DIRECTORY = "/webfile/";
106 
107 	private static final String ATTACH_SUFFIX = CmsConstants.ATTACHEMENT_SUFFIX;
108 
109 	// Slide instance
110 
111 	private NamespaceAccessToken namespace;
112 
113 	private Structure structure;
114 
115 	private Content content;
116 
117 	private Security security;
118 
119 	private Macro macro;
120 
121 	private Search search;
122 	
123 	private Logger log = Logger.getLogger(getClass());
124 
125 	public ContentsStoreServiceSlideImpl() throws Exception {
126 		InputStream iStream = ResourceUtils.getResourceAsStream("Domain.xml");
127 		Domain.init(iStream);
128 
129 		namespace = Domain.accessNamespace(new SecurityToken(""), Domain
130 				.getDefaultNamespace());
131 		structure = namespace.getStructureHelper();
132 		content = namespace.getContentHelper();
133 		security = namespace.getSecurityHelper();
134 		macro = namespace.getMacroHelper();
135 		search = namespace.getSearchHelper();
136 
137 		SlideRequiredInterceptor.init(namespace);
138 	}
139 
140 	public NamespaceAccessToken getNamespace() {
141 		return namespace;
142 	}
143 
144 	public List search(String siteName, String keyword) throws TgwSearchFailedException{
145 		String path = siteUri(siteName);
146 
147 		// create search elemnt
148 		SearchElement elem = new SearchElement();
149 		elem.addHref("");
150 		elem.addSearchKeyword(keyword);
151 
152 		// search
153 		SearchQueryResult result = doSearch("/", elem);
154 		return toResourceList(result, path);
155 	}
156 
157 	public List getLatestContents(String siteName, int size) throws TgwSearchFailedException {
158 		String path = siteUri(siteName);
159 
160 		// create search elemnt
161 		SearchElement elem = new SearchElement();
162 		elem.addHref("");
163 		elem.addExcludedCollectionElement();
164 		elem.addLimitElement(size);
165 		elem.addOrderElement();
166 
167 		// search
168 		SearchQueryResult result = doSearch(path, elem);
169 		return toResourceList(result);
170 	}
171 
172 	public void delete(String siteName, String pagePath) {
173 		String uri = pageUri(siteName, pagePath);
174 		SlideToken token = createNewSlideToken();
175 		try {
176 			macro.delete(token, uri, new MacroParameters(true, true));
177 		} catch (DeleteMacroException e) {
178 			log.log("ETGW0009",new Object[]{uri});
179 			e.printStackTrace();
180 		}
181 	}
182 
183 	public void rename(String siteName, String pagePath, String newPageName)
184 			throws TgwResourceAlreadyExistsException {
185 		String parentPath = PathUtils.getParentPath(pagePath);
186 		String newPagePath = (parentPath != null && parentPath.length() > 0) ? parentPath
187 				+ "/" + newPageName
188 				: newPageName;
189 		doMove(siteName, pagePath, newPagePath);
190 	}
191 
192 	public void move(String siteName, String pagePath, String newParentPath)
193 			throws TgwResourceAlreadyExistsException {
194 		String[] names = pagePath.split("/");
195 		String pageName = names[names.length - 1];
196 		String newPagePath = (newParentPath != null && newParentPath.length() > 0) ? newParentPath
197 				+ "/" + pageName
198 				: pageName;
199 		doMove(siteName, pagePath, newPagePath);
200 	}
201 	
202 	public void copy(String srcSiteName, String srcPath, String destSiteName, String destPath) throws TgwException{
203 		
204 		String srcUri = (srcPath == null)? siteUri(srcSiteName) : pageUri(srcSiteName,srcPath);
205 		String destUri = (destPath == null)? siteUri(destSiteName) : pageUri(destSiteName,destPath);
206 		
207 		SlideToken token = createNewSlideToken();
208 		try{
209 //			CopyListener copyListener = new TgwCopyMethod(token,content,structure);			
210 			macro.copy(token,srcUri,destUri);
211 //			macro.copy(token,srcUri,destUri,new MacroParameters(true,true,false),null,copyListener,null,null);
212 //			refreshCache(srcSiteName,true);
213 		}catch(CopyMacroException cme){
214 //			cme.printStackTrace();
215 			throw new TgwException("ETGW0006",new Object[]{srcUri,destUri},cme);
216 		}catch(DeleteMacroException dme){
217 //			dme.printStackTrace();
218 			throw new TgwException("ETGW0006",new Object[]{srcUri,destUri},dme);			
219 		}
220 	}
221 
222 	public void setProperty(String siteName, String path, Properties props)
223 			throws TgwResourceNotFoundException,TgwSecurityException, TgwException{
224 		
225 		String uri = pageUri(siteName, path);
226 		SlideToken token = createNewSlideToken();
227 		
228 		try{		
229 			NodeRevisionDescriptors descs = content.retrieve(token, uri);
230 			NodeRevisionDescriptor desc = content.retrieve(token, descs, descs.getLatestRevision());
231 			bindProperties(desc, props);
232 			content.store(token, uri, desc, null);
233 		}catch(ObjectNotFoundException e){
234 			throw new TgwResourceNotFoundException(new Object[]{uri});
235 		}catch(AccessDeniedException e){
236 			throw new TgwSecurityException("ETGW0010",new Object[]{uri},e);
237 		}catch(SlideException se){
238 			throw new TgwException("ETGW0008",new Object[]{siteName + "/" + path},se);			
239 		}
240 	}
241 
242 	public Properties getProperty(String siteName, String path)
243 			throws TgwResourceNotFoundException,TgwSecurityException,TgwException{
244 		String uri = pageUri(siteName, path);
245 		SlideToken token = createNewSlideToken();
246 		NodeRevisionDescriptor desc = null;
247 		try{
248 			NodeRevisionDescriptors descs = content.retrieve(token, uri);
249 			desc = content.retrieve(token, descs, descs.getLatestRevision());
250 		}catch(ObjectNotFoundException e){
251 			throw new TgwResourceNotFoundException(new Object[]{uri});
252 		}catch(AccessDeniedException e){
253 			throw new TgwSecurityException("ETGW0010",new Object[]{uri},e);
254 		}catch(SlideException se){
255 			throw new TgwException("ETGW0008",new Object[]{siteName + "/" + path},se);
256 		}
257 		return SlidePageFactory.getProperties(desc);
258 	}
259 
260 	public void removeProperty(String siteName, String path, String key)
261 			throws TgwResourceNotFoundException,TgwSecurityException,TgwException {
262 		String uri = pageUri(siteName, path);
263 		SlideToken token = createNewSlideToken();
264 		try{
265 			NodeRevisionDescriptors descs = content.retrieve(token, uri);
266 			NodeRevisionDescriptor desc = content.retrieve(token, descs, descs
267 					.getLatestRevision());
268 			desc.removeProperty(key);
269 			content.store(token, uri, desc, null);
270 		}catch(ObjectNotFoundException e){
271 			throw new TgwResourceNotFoundException(new Object[]{uri});
272 		}catch(AccessDeniedException e){
273 			throw new TgwSecurityException("ETGW0010",new Object[]{uri},e);
274 		}catch(SlideException se){
275 			throw new TgwException("ETGW0008",new Object[]{siteName + "/" + path},se);
276 		}		
277 	}
278 
279 	public void setPermissions(String siteName, String path,
280 			String[] grantRoles, String[] denyRoles) {
281 		String pageUri = pageUri(siteName, path);
282 		// doSetPermission(pageUri, grantRoles, denyRoles, true);
283 		doSetGrantPermission(pageUri, grantRoles, true);
284 	}
285 
286 	public boolean hasPermission(String siteName, String path, String roleName) {
287 		SlideToken token = createNewSlideToken();
288 		String uri = pageUri(siteName, path);
289 		SubjectNode role = getRole(roleName);
290 		return hasPermission(token, role, uri);
291 	}
292 
293 	private boolean hasPermission(SlideToken token, SubjectNode role, String uri) {
294 		
295 		boolean flag = true;
296 		boolean found = false;
297 
298 		try {
299 			ObjectNode resource = structure.retrieve(token, uri);
300 			Enumeration permissions = security.enumeratePermissions(token,resource);
301 
302 			while (permissions.hasMoreElements()) {
303 				NodePermission permission = (NodePermission) permissions.nextElement();
304 				String subjectUri = permission.getSubjectUri();
305 				boolean roleMatch = SubjectNode.ALL_URI.equals(subjectUri)
306 						|| subjectUri.equals(role.getUri());
307 				if (roleMatch) {
308 					found = true;
309 					flag = !permission.isNegative();
310 					break;
311 				}
312 			}
313 		} catch (ObjectNotFoundException e) {
314 			// do nothing
315 			log.log("ETGW0001",new Object[]{uri},e);
316 		} catch (AccessDeniedException e){
317 			log.log("ETGW0004",null,e);			
318 		
319 			found = true;
320 			flag = false;
321 		
322 		} catch (SlideException e){
323 			log.log("ETGW0012",null,e);
324 			e.printStackTrace();
325 		}
326 		
327 		String parentUri = PathUtils.getParentPath(uri);
328 		boolean parentExist = parentUri != null && !parentUri.equals("/")
329 				&& parentUri.length() > 0;
330 		if (!found && parentExist) {
331 			return hasPermission(token, role, parentUri);
332 		} else {
333 			return flag;
334 		}
335 	}
336 
337 	// this method is for upload file list
338 	public List getAttachmentFileList(String siteName, String pagePath)
339 			throws TgwSecurityException {
340 		String folder = attachmentFolder(pagePath);
341 		return getResources(siteName, folder, RETRIEVETYPE_PAGE, false);
342 	}
343 
344 	public List getRecursiveFolderList(String siteName, String path)
345 			throws TgwSecurityException {
346 		return getResources(siteName, path, RETRIEVETYPE_FOLDER, true);
347 	}
348 
349 	public List getRecursivePageList(String siteName, String path)
350 			throws TgwSecurityException {
351 		return getResources(siteName, path, RETRIEVETYPE_PAGE, true);
352 	}
353 
354 	public List getRecursivePageOrFolderList(String siteName, String path)
355 			throws TgwSecurityException {
356 		return getResources(siteName, path, RETRIEVETYPE_PAGEFOLDER, true);
357 	}
358 
359 	public List getPageOrFolderList(String siteName, String path)
360 			throws TgwSecurityException {
361 		return getResources(siteName, path, RETRIEVETYPE_PAGEFOLDER, false);
362 	}
363 
364 	public List getFolderList(String siteName, String path) 
365 	throws TgwSecurityException {
366 		return getResources(siteName, path, RETRIEVETYPE_FOLDER, false);
367 	}
368 
369 	public List getPageList(String siteName, String path) 
370 	throws TgwSecurityException {
371 		return getResources(siteName, path, RETRIEVETYPE_PAGE, false);
372 	}
373 
374 	/***
375 	 * @deprecated
376 	 */
377 	public boolean isExistPage(String siteName, String pagePath)
378 			throws TgwSecurityException {
379 		return isExistResource(siteName, pagePath, true);
380 	}
381 
382 	/***
383 	 * @deprecated
384 	 */
385 	public boolean isExist(String siteName, String path)
386 			throws TgwSecurityException {
387 		return isExistResource(siteName, path, false);
388 	}
389 
390 	public void createAttachment(String siteName, String pagePath,
391 			String fileName, String contentType, int contentLength,
392 			InputStream iStream) throws TgwSecurityException, TgwResourceCreationException{
393 
394 		String uri = attachmentUri(siteName, pagePath, fileName);
395 		checkParentDirectory(uri);
396 		doCreateContent(uri, contentType, contentLength, iStream, null);
397 	}
398 
399 	public void createResource(String siteName, String path,
400 			String contentType, int contentLength, InputStream inputStream)
401 			throws TgwResourceCreationException {
402 
403 		String uri = pageUri(siteName, path);
404 		doCreateContent(uri, contentType, contentLength, inputStream, null);
405 	}
406 
407 	/***
408 	 * @deprecated
409 	 */
410 	public boolean checkVersion(Resource resource, String version) {
411 		String uri = pageUri(resource.getSiteName(), resource.getPath());
412 		SlideToken token = createNewSlideToken();
413 		boolean confict = false;
414 		try {
415 			NodeRevisionDescriptors descriptors = content.retrieve(token, uri);
416 			NodeRevisionNumber num = descriptors.getLatestRevision();
417 			if (num != null && version != null) {
418 				confict = !(version.equals(num.toString()));
419 			}
420 		} catch (ObjectNotFoundException e) {
421 			// do nithing
422 		} catch (AccessDeniedException e) {
423 			e.printStackTrace();
424 		} catch (LinkedObjectNotFoundException e) {
425 			e.printStackTrace();
426 		} catch (ObjectLockedException e) {
427 			e.printStackTrace();
428 		} catch (ServiceAccessException e) {
429 			e.printStackTrace();
430 		} catch (VetoException e) {
431 			e.printStackTrace();
432 		}
433 		return confict;
434 	}
435 
436 	public void createPage(Page page) throws TgwResourceCreationException {
437 
438 		Resource resource = page.getResource();
439 		String uri = pageUri(resource.getSiteName(), resource.getPath());
440 
441 		InputStream contentStream = null;
442 		if (page.getContent() instanceof String) {
443 			contentStream = CharUtil.toInputStream((String) page.getContent());
444 		}
445 		String contentType = resource.getContentType();	
446 		doCreateContent(uri, contentType, resource.getContentLength(),
447 				contentStream, resource.getProperties());
448 
449 	}
450 
451 	public Diff getDiff(String siteName, String pagePath, String version) {
452 		String uri = pageUri(siteName, pagePath);
453 		SlideToken token = createNewSlideToken();
454 
455 		Diff diff = null;
456 
457 		try {
458 			NodeRevisionDescriptors descs = content.retrieve(token, uri);
459 			NodeRevisionNumber lastNum = descs.getLatestRevision();
460 			NodeRevisionNumber oldNum = new NodeRevisionNumber(version);
461 
462 			NodeRevisionDescriptor lastDesc = content.retrieve(token, descs,
463 					lastNum);
464 			NodeRevisionDescriptor oldDesc = content.retrieve(token, descs,
465 					oldNum);
466 
467 			NodeRevisionContent latestContent = content.retrieve(token, uri,
468 					lastDesc);
469 
470 			NodeRevisionContent oldContent = content.retrieve(token, uri,
471 					oldDesc);
472 
473 			diff = new Diff(new String(oldContent.getContentBytes(),
474 					DEFAULT_ENCODING), new String(latestContent
475 					.getContentBytes(), DEFAULT_ENCODING));
476 
477 		} catch (ObjectNotFoundException notFound) {
478 			// do nothing
479 		} catch (Exception e) {
480 			e.printStackTrace();
481 			throw new RuntimeException(e);
482 		}
483 		return diff;
484 	}
485 
486 	/***
487 	 * @deprecated
488 	 */
489 	public String getContent(Resource resource) throws TgwSecurityException {
490 		Page page = getPage(resource.getSiteName(), resource.getPath());
491 		if (page == null) {
492 			return null;
493 		}
494 		return (String) page.getContent();
495 	}
496 
497 	public Resource getResource(String siteName, String pagePath) throws TgwSecurityException{
498 		String uri = pageUri(siteName, pagePath);
499 		try{
500 			return getResource(uri, siteName, pagePath);
501 		}catch(TgwResourceNotFoundException trnfe){
502 			return null;
503 		}
504 	}
505 
506 	public Resource getAttachmentResource(String siteName, String pagePath,
507 			String fileName) throws TgwSecurityException, TgwResourceNotFoundException{
508 		String uri = attachmentUri(siteName, pagePath, fileName);
509 		return getResource(uri, siteName, pagePath);
510 	}
511 
512 	public Page getPage(String siteName, String pagePath)
513 			throws TgwSecurityException {
514 		String uri = pageUri(siteName, pagePath);
515 		SlideToken token = createNewSlideToken(false);
516 
517 		Page page = null;
518 		try {
519 			NodeRevisionDescriptors descs = content.retrieve(token, uri);
520 			NodeRevisionNumber revisionNumber = descs.getLatestRevision();
521 			NodeRevisionNumber initialNumber = descs.getInitialRevision();
522 			NodeRevisionDescriptor desc = content.retrieve(token, descs);
523 			NodeRevisionDescriptor initialDesc = content.retrieve(token, descs,
524 					initialNumber);
525 			NodeRevisionContent data = content.retrieve(token, uri, desc);
526 			page = SlidePageFactory.createPage(siteName, pagePath, descs,
527 					revisionNumber, desc, initialDesc, data);
528 
529 		} catch (ObjectNotFoundException notFound) {
530 			// do nothing
531 		} catch (AccessDeniedException e) {
532 			throw new TgwSecurityException(e);
533 		} catch (LinkedObjectNotFoundException e) {
534 			// TODO Auto-generated catch block
535 			e.printStackTrace();
536 		} catch (RevisionDescriptorNotFoundException e) {
537 			// TODO Auto-generated catch block
538 			e.printStackTrace();
539 		} catch (ObjectLockedException e) {
540 			// TODO Auto-generated catch block
541 			e.printStackTrace();
542 		} catch (ServiceAccessException e) {
543 			// TODO Auto-generated catch block
544 			e.printStackTrace();
545 		} catch (VetoException e) {
546 			// TODO Auto-generated catch block
547 			e.printStackTrace();
548 		} catch (RevisionNotFoundException e) {
549 			// TODO Auto-generated catch block
550 			e.printStackTrace();
551 		} catch (RevisionContentNotFoundException e) {
552 			// TODO Auto-generated catch block
553 			e.printStackTrace();
554 		}
555 		return page;
556 	}
557 
558 	public void writeAttachment(String siteName, String pagePath,
559 			String fileName, OutputStream os) throws IOException {
560 		String uri = attachmentUri(siteName, pagePath, fileName);
561 		CopyUtils.copy(getAttachmentInputStream(uri), os);
562 	}
563 
564 	public void writeResource(String siteName, String pagePath, OutputStream os)
565 			throws IOException {
566 		String uri = pageUri(siteName, pagePath);
567 		CopyUtils.copy(getAttachmentInputStream(uri), os);
568 	}
569 
570 	public List getHistory(String siteName, String pagePath) {
571 		List list = new ArrayList();
572 
573 		String uri = pageUri(siteName, pagePath);
574 		SlideToken token = createNewSlideToken();
575 
576 		try {
577 			NodeRevisionDescriptors descs = content.retrieve(token, uri);
578 			Enumeration enm = descs.enumerateRevisionNumbers();
579 
580 			while (enm.hasMoreElements()) {
581 				NodeRevisionNumber num = (NodeRevisionNumber) enm.nextElement();
582 				Resource resource = getResource(token, siteName, pagePath,
583 						descs, num);
584 				list.add(resource);
585 			}
586 		} catch (ObjectNotFoundException notFound) {
587 			// do nothing
588 		} catch (Exception e) {
589 			e.printStackTrace();
590 		}
591 
592 		Collections.sort(list, new Comparator() {
593 			public boolean equals(Object obj) {
594 				return (super.equals(obj));
595 			}
596 
597 			public int compare(Object obj1, Object obj2) {
598 				Resource page1 = (Resource) obj1;
599 				Resource page2 = (Resource) obj2;
600 				int minor1 = Integer
601 						.parseInt(page1.getVersion().split("//.")[1]);
602 				int minor2 = Integer
603 						.parseInt(page2.getVersion().split("//.")[1]);
604 				return minor1 - minor2;
605 			}
606 		});
607 
608 		return list;
609 	}
610 
611 	public void createFolder(String siteName, String folderPath)
612 			throws TgwSecurityException, TgwResourceAlreadyExistsException {
613 		String uri = pageUri(siteName, folderPath);
614 		try {
615 			createDirectory(uri);
616 		} catch(TgwResourceCreationException e){
617 			throw new RuntimeException(e);
618 		}
619 	}
620 
621 	public void copyFromFileSystem(File srcDirectory, String targetSiteName)
622 			throws TgwResourceCreationException, TgwSecurityException{
623 		if (!isExistResource(targetSiteName, "", false)) {
624 			try{
625 				createFolder(targetSiteName, "");
626 			}catch(TgwResourceAlreadyExistsException e){				
627 			}
628 		}
629 		doCopyFromFileSystem(srcDirectory, targetSiteName, "");
630 	}
631 
632 	public void copyToFileSystem(String srcSiteName, String srcPath,
633 			File targetDirectory) throws TgwSecurityException,IOException{
634 		List list = getRecursivePageOrFolderList(srcSiteName, srcPath);
635 		Iterator itr = list.iterator();
636 		while (itr.hasNext()) {
637 			Resource resource = (Resource) itr.next();
638 			String path = resource.getPath();
639 			path = PathUtils.getRelativePath(srcPath, path);
640 			File newFile = new File(PathUtils.join(targetDirectory.getPath(),
641 					path));
642 			if (resource.isFolder()) {
643 				newFile.mkdir();
644 			} else {
645 				OutputStream os = ResourceUtils.getOutputStream(newFile);
646 				writeResource(srcSiteName, resource.getPath(), os);
647 				IOUtils.closeQuietly(os);
648 			}
649 		}
650 	}
651 
652 	public void createThumbnail(Resource resource, OutputStream os, int width,
653 			String formatName) {
654 		InputStream is = getAttachmentInputStream(resource);
655 		try {
656 			ImageUtils.createThumbnail(is, os, width, formatName);
657 		} catch (IOException e) {
658 			e.printStackTrace();
659 		}
660 	}
661 
662 	public InputStream getInputStream(String siteName, String path) {
663 		String uri = pageUri(siteName, path);
664 		SlideToken token = createNewSlideToken();
665 		InputStream is = null;
666 		try {
667 			NodeRevisionDescriptors descs = content.retrieve(token, uri);
668 			NodeRevisionDescriptor desc = content.retrieve(token, descs);
669 			NodeRevisionContent data = content.retrieve(token, uri, desc);
670 			is = data.streamContent();
671 
672 			StringWriter writer = new StringWriter();
673 			CopyUtils.copy(is, writer, "Windows-31J");
674 
675 		} catch (ObjectNotFoundException notFound) {
676 			// do nothing
677 		} catch (Exception e) {
678 			e.printStackTrace();
679 			throw new RuntimeException(e);
680 		}
681 		return is;
682 	}
683 
684 	public void refreshCache(String siteName) {
685 		String uri = pageUri(siteName, "");
686 		SlideToken token = createNewSlideToken();
687 
688 		Uri objectUri = namespace.getUri(token, uri);
689 		Store store = objectUri.getStore();
690 		if (store instanceof ExtendedStore) {
691 			ExtendedStore estore = (ExtendedStore) store;
692 			estore.resetCache();
693 		}
694 	}
695 	
696 	public void refreshCache(String path, boolean isSite) {
697 		
698 		if(isSite){
699 			refreshCache(path);
700 		}else{
701 			
702 		}		
703 		SlideToken token = createNewSlideToken();
704 
705 		Uri objectUri = namespace.getUri(token, path);
706 		Store store = objectUri.getStore();
707 		if (store instanceof ExtendedStore) {
708 			ExtendedStore estore = (ExtendedStore) store;
709 			estore.resetCache();
710 		}
711 	}
712 
713 	// [Start] ---- Private Method ------
714 
715 	private InputStream getAttachmentInputStream(Resource resource) {
716 		String uri = uri(resource);
717 		return getAttachmentInputStream(uri);
718 	}
719 
720 	private InputStream getAttachmentInputStream(String uri) {
721 		SlideToken token = createNewSlideToken();
722 		InputStream is = null;
723 		try {
724 			NodeRevisionDescriptors descs = content.retrieve(token, uri);
725 			NodeRevisionDescriptor desc = content.retrieve(token, descs);
726 			NodeRevisionContent data = content.retrieve(token, uri, desc);
727 			is = data.streamContent();
728 		} catch (ObjectNotFoundException notFound) {
729 			// do nothing
730 		} catch (Exception e) {
731 			e.printStackTrace();
732 			throw new RuntimeException(e);
733 		}
734 		return is;
735 	}
736 
737 	private void createDirectory(String uri) throws 
738 	TgwSecurityException,TgwResourceAlreadyExistsException,TgwResourceCreationException {
739 	
740 		SlideToken token = createNewSlideToken();
741 		NodeRevisionDescriptor revisionDescriptor = null;
742 
743 		try {
744 			revisionDescriptor = content.retrieve(token, content.retrieve(
745 					token, uri));
746 		} catch (ObjectNotFoundException oe) {
747 			revisionDescriptor = new NodeRevisionDescriptor();
748 		} catch(AccessDeniedException e){
749 			throw new TgwSecurityException(e);
750 		}catch(SlideException e){
751 			throw new TgwResourceCreationException(new Object[]{uri},e);
752 		}
753 
754 		bindRevisionDescriptor(revisionDescriptor, token,
755 				NodeRevisionDescriptor.COLLECTION_TYPE);
756 		revisionDescriptor.setContentLength(0);
757 
758 		// create object
759 		SubjectNode subject = new SubjectNode();
760 		try{
761 			structure.create(token, subject, uri);
762 			content.create(token, uri, revisionDescriptor, null);			
763 		}catch(ObjectAlreadyExistsException e){
764 			throw new TgwResourceAlreadyExistsException(new Object[]{uri},e);
765 		}catch(AccessDeniedException e){
766 			throw new TgwSecurityException(e);			
767 		}catch(SlideException e){
768 			throw new TgwResourceCreationException(new Object[]{uri},e);			
769 		}
770 	}
771 
772 	private void bindRevisionDescriptor(NodeRevisionDescriptor desc,
773 			SlideToken token, String resourceType){
774 				
775 		try{
776 			String creationUser = ((SubjectNode) security.getPrincipal(token)).getPath().lastSegment();
777 			desc.setCreationUser(creationUser);
778 			desc.setModificationUser(creationUser);			
779 			desc.setOwner(creationUser);
780 		}catch(SlideException e){
781 			log.log("ETGW0013",null,e);
782 		}
783 		
784 		desc.setResourceType(resourceType);
785 		desc.setCreationDate(new Date());
786 		desc.setModificationDate(new Date());
787 		desc.setLastModified(new Date());
788 		desc.setSource("");		
789 	}
790 
791 	private String computeEtag(String uri, NodeRevisionDescriptor nrd){
792 		
793 		StringBuffer buf = new StringBuffer();
794 		buf.append(System.currentTimeMillis() + "_");
795 		buf.append(uri.hashCode() + "_");
796 		buf.append(nrd.getLastModified() + "_");
797 		buf.append(nrd.getContentLength() + "");
798 		
799 		return new String(DigestUtils.md5Hex(buf.toString()));
800 	}
801 
802 	private List toResourceList(SearchQueryResult result) {
803 		return toResourceList(result, null);
804 	}
805 
806 	private List toResourceList(SearchQueryResult result, String filterUri) {
807 		List list = new ArrayList();
808 		for (Iterator i = result.iterator(); i.hasNext();) {
809 			ComparableResource cresource = (ComparableResource) i.next();
810 
811 			
812 			try {
813 				String uri = cresource.getUri();
814 				if (filterUri != null && !uri.startsWith(filterUri)) {
815 					continue;
816 				}
817 				uri = CharUtil.charpop(uri, '/');
818 				String[] uriArray = uri.split("/");
819 				if (uriArray.length < 3) {
820 					continue;
821 				}
822 				// String wiki = uriArray[0];
823 				String siteName = uriArray[1];
824 				String pagePath = CharUtil.join(2, uriArray, "/");
825 				try{
826 					Resource resource = getResource(siteName, pagePath);
827 					list.add(resource);
828 				}catch(TgwSecurityException tse){// do-nothing, next					
829 				}
830 			} catch (SlideException e) {
831 				log.log("WTGW0001",null,e);
832 			}
833 		}
834 		return list;
835 	}
836 
837 	private SearchQueryResult doSearch(String path, SearchElement searchElem)
838 			throws TgwSearchFailedException{
839 		SlideToken token = createNewSlideToken(false);
840 		token.addParameter("slideContextPath", "");
841 		
842 		SearchQueryResult result= null;
843 		try{
844 		SearchQuery query = search.createSearchQuery(
845 				NodeProperty.NamespaceCache.DEFAULT_URI, searchElem.getRoot(),
846 				token, 5, path);
847 		result = search.search(token, query);
848 		
849 		}catch(SlideException e){
850 			throw new TgwSearchFailedException(e);
851 		}
852 		return result;
853 	}
854 
855 	private List getResources(String siteName, String path, int retrieveType,
856 			boolean isRecursive) throws TgwSecurityException {
857 
858 		String parentUri = pageUri(siteName, path);
859 		SlideToken token = createNewSlideToken(false);
860 		List list = new ArrayList();
861 
862 		try {
863 			ObjectNode node = structure.retrieve(token, parentUri);
864 			Enumeration children = structure.getChildren(token, node);
865 
866 			while (children.hasMoreElements()) {
867 				ObjectNode obj = (ObjectNode) children.nextElement();
868 
869 				if (obj instanceof LinkNode) { // Ignore LinkNode
870 					continue;
871 				}
872 
873 				String childPath = path + "/" + obj.getPath().lastSegment();
874 				String childUri = parentUri + "/" + obj.getPath().lastSegment();
875 
876 				NodeRevisionDescriptors descs = content.retrieve(token,
877 						childUri);
878 				NodeRevisionNumber num = descs.getLatestRevision();
879 				Resource childResource = getResource(token, siteName,
880 						childPath, descs, num);
881 
882 				if (childResource.isFolder()) {
883 					switch (retrieveType) {
884 					case RETRIEVETYPE_PAGE:
885 						break; // do nothing
886 					default:
887 						list.add(childResource);
888 						break;
889 					}
890 					if (isRecursive) {
891 						List grandChildren = getResources(siteName, childPath,
892 								retrieveType, true);
893 						list.addAll(grandChildren);
894 					}
895 				} else {
896 					switch (retrieveType) {
897 					case RETRIEVETYPE_FOLDER:
898 						break; // do nothing
899 					default:
900 						list.add(childResource);
901 						break;
902 					}
903 				}
904 			}
905 		} catch (ObjectNotFoundException e) {
906 			log.log("WTGW0002",new Object[]{e.getMessage()});
907 		} catch (AccessDeniedException e) {
908 			throw new TgwSecurityException(e);
909 		} catch (SlideException e) {
910 			log.log("WTGW0003",null,e);
911 		} 
912 		return list;
913 	}
914 
915 	public boolean isExistResource(String siteName, String path,
916 			boolean pageOnly) throws TgwSecurityException {
917 		String uri = pageUri(siteName, path);
918 		return isExist(uri, pageOnly);
919 	}
920 
921 	/***
922 	 * Create Slide Token from HttpServletRequest
923 	 * 
924 	 * @return
925 	 */
926 	private SlideToken createNewSlideToken() {
927 		return createNewSlideToken(true);
928 	}
929 	
930 	private SlideToken createNewSlideToken(boolean forceStoreEnlistment){
931 		Principal principal = TgwContext.getPrincipal();
932 		CredentialsToken cToken = null;
933 		if (principal == null) {
934 			cToken = new CredentialsToken((String) null);
935 		} else {
936 			cToken = new CredentialsToken(principal);
937 		}
938 		SlideToken token = new SlideTokenImpl(cToken);
939 		token.setForceStoreEnlistment(forceStoreEnlistment);
940 		return token;		
941 	}	
942 
943 	private SubjectNode getRole(String roleName) {
944 		String rolePath = namespace.getNamespaceConfig().getRolesPath();
945 		SubjectNode role = SubjectNode
946 				.getSubjectNode(rolePath + "/" + roleName);
947 		if (SecurityService.ROLE_UNAUTHENTICATED.equals(roleName)) {
948 			role = SubjectNode.UNAUTHENTICATED;
949 		}
950 		return role;
951 	}
952 
953 	private void doCreateContent(String uri, String contentType,
954 			int contentLength, InputStream contentStream, Properties props)
955 			 throws TgwResourceCreationException{
956 		
957 		if (props == null) {
958 			props = new Properties();
959 		}
960 
961 		SlideToken token = createNewSlideToken();
962 		NodeRevisionNumber lastRevision = null;
963 		SubjectNode subjectNode = null;
964 		boolean isNewlyCreate = false;
965 		
966 		try {
967 			subjectNode = (SubjectNode) structure.retrieve(token, uri);
968 			NodeRevisionDescriptors descs = content.retrieve(token, uri);
969 			lastRevision = descs.getLatestRevision();
970 			NodeRevisionDescriptor desc = content.retrieve(token, descs, lastRevision);
971 			Properties lastProps = SlidePageFactory.getProperties(desc);
972 
973 			for (Iterator i = lastProps.keySet().iterator(); i.hasNext();) {
974 				String key = (String) i.next();
975 				if (!props.containsKey(key)) {
976 					props.put(key, lastProps.get(key));
977 				}
978 			}
979 		} catch (ObjectNotFoundException e) {
980 			isNewlyCreate = true;
981 		} catch(SlideException e){
982 			throw new TgwResourceCreationException(new Object[]{uri}, e);			
983 		} 
984 			
985 		if(subjectNode == null && isNewlyCreate){
986 			subjectNode = new SubjectNode();
987 			subjectNode.setUri(uri);
988 			try{
989 				structure.create(token, subjectNode, uri);
990 			}catch(SlideException e){
991 				throw new TgwResourceCreationException(new Object[]{uri}, e);
992 			}
993 		}
994 
995 		if (lastRevision != null)
996 			lastRevision = new NodeRevisionNumber(lastRevision, false);
997 		else
998 			lastRevision = new NodeRevisionNumber();
999 
1000 		// create node revision descriptor
1001 		NodeRevisionDescriptor desc = createRevisionDescriptor(token,lastRevision,contentType,contentLength,uri,props);
1002 		
1003 		// create content
1004 		NodeRevisionContent revisionContent = new NodeRevisionContent();
1005 		revisionContent.setContent(contentStream);
1006 		
1007 		// important to create NodeRevisionDescriptors separately
1008 		// to be able to tell it to use versioning
1009 		try{
1010 			if (lastRevision.toString().equals("1.0")){
1011 				content.create(token, uri, true);
1012 			}
1013 			content.create(token, uri, desc, revisionContent);
1014 		}catch(SlideException e){
1015 			throw new TgwResourceCreationException(new Object[]{uri},e);
1016 		}
1017 	}
1018 	
1019 	private NodeRevisionDescriptor createRevisionDescriptor(SlideToken token, NodeRevisionNumber lastRevision,
1020 			String contentType,int contentLength,String uri,Properties props){
1021 		
1022 		NodeRevisionDescriptor desc = 
1023 			new NodeRevisionDescriptor(lastRevision, NodeRevisionDescriptors.MAIN_BRANCH,
1024 					new Vector(), new Hashtable());
1025 
1026 		bindRevisionDescriptor(desc, token, "");
1027 		desc.setContentLanguage("en");
1028 		desc.setETag(computeEtag(uri, desc));
1029 		desc.setContentType(contentType);
1030 		desc.setContentLength(contentLength);
1031 
1032 		bindProperties(desc, props);
1033 		return desc;
1034 	}
1035 	
1036 	private boolean isExist(String uri, boolean fileOnly)
1037 			throws TgwSecurityException {
1038 		SlideToken token = createNewSlideToken(false);
1039 		NodeRevisionDescriptor desc = null;
1040 		try {
1041 			structure.retrieve(token, uri);
1042 			NodeRevisionDescriptors descs = content.retrieve(token, uri);
1043 			desc = content.retrieve(token, descs);
1044 		} catch (ObjectNotFoundException e) {
1045 			return false;
1046 		} catch (AccessDeniedException e) {
1047 			throw new TgwSecurityException(e);
1048 		} catch (Exception e) {
1049 			e.printStackTrace();
1050 			throw new RuntimeException(e);
1051 		}
1052 
1053 		if (fileOnly) {
1054 			return !SlidePageFactory.isFolderFlag(desc);
1055 		} else {
1056 			return true;
1057 		}
1058 	}
1059 
1060 	private void checkParentDirectory(String uri) throws TgwSecurityException, TgwResourceCreationException {
1061 		String parentUri = PathUtils.getParentPath(uri);
1062 		if (!isExist(parentUri,false)) {
1063 			checkParentDirectory(parentUri);
1064 			try{
1065 				createDirectory(parentUri);
1066 			}catch(TgwResourceAlreadyExistsException e){				
1067 			}
1068 		}
1069 	}
1070 
1071 	private void doMove(String siteName, String sourcePath, String targetPath)
1072 			throws TgwResourceAlreadyExistsException {
1073 		try {
1074 			if (isExistResource(siteName, targetPath, false)) {
1075 				throw new TgwResourceAlreadyExistsException(new Object[]{siteName + "/" + targetPath});
1076 			}
1077 			if (isExistResource(siteName, targetPath + ATTACH_SUFFIX, false)) {
1078 				throw new TgwResourceAlreadyExistsException(new Object[]{siteName + "/" + targetPath + ATTACH_SUFFIX});
1079 			}
1080 			doMove_(siteName, sourcePath, targetPath);
1081 			if (isExistResource(siteName, sourcePath + ATTACH_SUFFIX, false)) {
1082 				doMove_(siteName, sourcePath + ATTACH_SUFFIX, targetPath + ATTACH_SUFFIX);
1083 			}
1084 		} catch (CopyMacroException e) {
1085 			e.printStackTrace();
1086 		} catch (DeleteMacroException e) {
1087 			e.printStackTrace();
1088 		} catch (TgwSecurityException e) {
1089 			e.printStackTrace();
1090 		}
1091 	}
1092 
1093 	private void doMove_(String siteName, String sourcePath, String targetPath)
1094 			throws CopyMacroException, DeleteMacroException {
1095 		String sourceUri = pageUri(siteName, sourcePath);
1096 		String targetUri = pageUri(siteName, targetPath);
1097 
1098 		SlideToken token = createNewSlideToken();
1099 		macro.move(token, sourceUri, targetUri);
1100 	}
1101 
1102 	private Resource getResource(String uri, String siteName, String pagePath)
1103 			throws TgwSecurityException, TgwResourceNotFoundException {
1104 		SlideToken token = createNewSlideToken(false);
1105 		Resource resource = null;
1106 		try {
1107 			NodeRevisionDescriptors descs = content.retrieve(token, uri);
1108 			NodeRevisionNumber num = descs.getLatestRevision();
1109 			resource = getResource(token, siteName, pagePath, descs, num);
1110 		} catch (ObjectNotFoundException notFound) {
1111 			throw new TgwResourceNotFoundException(new Object[]{pagePath,siteName},notFound);
1112 		} catch (AccessDeniedException e) {
1113 			throw new TgwSecurityException(e);
1114 		} catch (Exception e) {
1115 			e.printStackTrace();
1116 			throw new RuntimeException(e);
1117 		}
1118 		return resource;
1119 	}
1120 
1121 	private void bindProperties(NodeRevisionDescriptor desc, Properties props) {
1122 		Enumeration penum = props.keys();
1123 		while (penum.hasMoreElements()) {
1124 			String key = (String) penum.nextElement();
1125 			String value = props.getProperty(key);
1126 			if (value != null && !value.equals(""))
1127 				desc.setProperty(key, value);
1128 		}
1129 	}
1130 
1131 	private Resource getResource(SlideToken token, String siteName,
1132 			String pageName, NodeRevisionDescriptors descs,
1133 			NodeRevisionNumber num) throws ObjectNotFoundException,
1134 			AccessDeniedException, LinkedObjectNotFoundException,
1135 			RevisionDescriptorNotFoundException, ObjectLockedException,
1136 			ServiceAccessException, VetoException {
1137 
1138 		NodeRevisionDescriptor desc = content.retrieve(token, descs, num);
1139 		NodeRevisionNumber initialNum = descs.getInitialRevision();
1140 		NodeRevisionDescriptor initialDesc = content.retrieve(token, descs,
1141 				initialNum);
1142 		return SlidePageFactory.createResource(siteName, pageName, descs, num,
1143 				desc, initialDesc);
1144 	}
1145 
1146 	private void doSetGrantPermission(String uri, String[] grantRoles,
1147 			boolean inheritable) {
1148 		SlideToken token = createNewSlideToken();
1149 
1150 		try {
1151 			ObjectNode resource = structure.retrieve(token, uri);
1152 			Vector vec = new Vector();
1153 
1154 			if (grantRoles == null || grantRoles.length == 0
1155 					|| SecurityUtils.hasUnauthenticated(grantRoles)) {
1156 				NodePermission permission = new NodePermission(resource,
1157 						SubjectNode.ALL, ActionNode.ALL, inheritable, false);
1158 				// grant // all
1159 				vec.add(permission);
1160 			} else {
1161 				for (int i = 0; i < grantRoles.length; i++) {
1162 					SubjectNode role = getRole(grantRoles[i]);
1163 					NodePermission permission = new NodePermission(resource,
1164 							role, ActionNode.ALL, inheritable, false); // grant
1165 					// role
1166 					vec.addElement(permission);
1167 				}
1168 				NodePermission permission = new NodePermission(resource,
1169 						SubjectNode.ALL, ActionNode.ALL, inheritable, true); // deny
1170 				// //
1171 				// all
1172 				vec.add(permission);
1173 			}
1174 			security.setPermissions(token, uri, vec.elements());
1175 
1176 		} catch (ObjectNotFoundException e) {
1177 			// do nothing
1178 		} catch (LinkedObjectNotFoundException e) {
1179 			e.printStackTrace();
1180 		} catch (AccessDeniedException e) {
1181 			e.printStackTrace();
1182 		} catch (ServiceAccessException e) {
1183 			e.printStackTrace();
1184 		} catch (VetoException e) {
1185 			e.printStackTrace();
1186 		}
1187 	}
1188 
1189 	// [Start] ----- Create Path ------
1190 
1191 	private static final String uri(Resource resource) {
1192 		return PAGE_DIRECTORY + resource.getSiteName() + "/"
1193 				+ resource.getPath();
1194 	}
1195 
1196 	private static final String siteUri(String siteName) {
1197 		return PAGE_DIRECTORY + siteName;
1198 	}
1199 
1200 	private static final String pageUri(String siteName, String pagePath) {
1201 		return PAGE_DIRECTORY + siteName + "/" + pagePath;
1202 	}
1203 
1204 	private static final String attachmentUri(String siteName, String pagePath,
1205 			String fileName) {
1206 		return PAGE_DIRECTORY + siteName + "/" + pagePath + ATTACH_SUFFIX + "/"
1207 				+ fileName;
1208 	}
1209 
1210 	private static final String attachmentFolder(String pagePath) {
1211 		return pagePath + ATTACH_SUFFIX;
1212 	}
1213 
1214 	private void doCopyFromFileSystem(File srcDirectory, String siteName,
1215 			String prefix) throws TgwResourceCreationException, TgwSecurityException{
1216 		File[] children = srcDirectory.listFiles();
1217 		for (int i = 0; i < children.length; i++) {
1218 			File child = children[i];
1219 			String path = PathUtils.join(prefix, child.getName());
1220 			if (child.isDirectory()) {
1221 				if (!isExistResource(siteName, path, false)) {
1222 					try{
1223 						createFolder(siteName, path);
1224 					}catch(TgwResourceAlreadyExistsException e){
1225 					}
1226 				}
1227 				doCopyFromFileSystem(child, siteName, path);
1228 			} else {
1229 				String content = ResourceUtils.readContent(child);
1230 				String extension = PathUtils.getExtension(path);
1231 				String contentType = MimeMappings.getContentType(extension);
1232 				Resource resource = new ResourceImpl(siteName, path,
1233 						contentType);
1234 				Page page = new PageImpl(resource, content);
1235 				createPage(page);
1236 			}
1237 		}
1238 	}
1239 
1240 	// [End] ---- Private Metdho ------
1241 }