1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.seasar.tuigwaa.system;
17
18 import java.io.File;
19 import java.io.IOException;
20 import java.security.Principal;
21 import java.util.ArrayList;
22 import java.util.Date;
23 import java.util.HashMap;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.jar.JarInputStream;
28 import java.util.jar.JarOutputStream;
29
30 import javax.servlet.http.HttpServletRequest;
31
32 import org.apache.commons.io.filefilter.SuffixFileFilter;
33 import org.apache.commons.lang.ArrayUtils;
34 import org.apache.commons.lang.StringUtils;
35 import org.apache.commons.logging.Log;
36 import org.apache.commons.logging.LogFactory;
37 import org.seasar.tuigwaa.cms.ContentsService;
38 import org.seasar.tuigwaa.cms.TgwResourceAlreadyExistsException;
39 import org.seasar.tuigwaa.controller.ControllerService;
40 import org.seasar.tuigwaa.database.BasicDatabaseService;
41 import org.seasar.tuigwaa.logic.LogicService;
42 import org.seasar.tuigwaa.model.ModelService;
43 import org.seasar.tuigwaa.plugin.PluginService;
44 import org.seasar.tuigwaa.security.Action;
45 import org.seasar.tuigwaa.security.SecurityUtils;
46 import org.seasar.tuigwaa.util.TgwContext;
47 import org.seasar.tuigwaa.util.TgwPathResolver;
48
49 import com.isenshi.util.ResourceUtils;
50 import com.isenshi.util.extlib.DiconResource;
51
52 /***
53 * @author nishioka
54 */
55 public class SiteServiceImpl implements SiteService {
56
57 private List siteConfigs = new ArrayList();
58
59 private Map siteConfigMap = new HashMap();
60
61 private ControllerService controller;
62
63 private ModelService model;
64
65 private BasicDatabaseService db;
66
67 private ContentsService contents;
68
69 private LogicService logicService;
70
71 private PluginService pluginService;
72
73 private DesignService designService;
74
75 private ServiceHelper helper;
76
77 private Log log = LogFactory.getLog(getClass());
78
79 private String defaultInitpageName;
80
81 private String defaultMenupageName;
82
83 public SiteServiceImpl(ControllerService strutsService,
84 ModelService entityService, BasicDatabaseService dbService,
85 ContentsService contentsService, LogicService logicService,
86 PluginService pluginService, DesignService designService,
87 ServiceHelper helper) {
88 this.controller = strutsService;
89 this.model = entityService;
90 this.db = dbService;
91 this.contents = contentsService;
92 this.logicService = logicService;
93 this.pluginService = pluginService;
94 this.designService = designService;
95 this.helper = helper;
96 }
97
98 public void initSkins() {
99 designService.init();
100 }
101
102 public void createSite(SiteConfig siteConfig) {
103 doCreateSite(siteConfig, true);
104 }
105
106 public void deleteSite(String siteName) {
107 try {
108 contents.deleteSite(siteName);
109 model.deleteDomain(siteName);
110 ResourceUtils.deleteDirectory(TgwPathResolver
111 .getSiteDirectory(siteName));
112 deleteSiteLocalDirectory(siteName);
113
114 SiteConfig siteConfig = (SiteConfig) siteConfigMap.remove(siteName);
115 controller.deleteSite(siteName);
116 siteConfigs.remove(siteConfig);
117 } catch (Exception e) {
118
119 e.printStackTrace();
120 }
121 }
122
123 public void loadAllSites() {
124 db.loadExternalDatabase();
125 pluginService.loadPlugins();
126
127 String[] siteNames = getSiteNames();
128 if (siteNames == null) {
129 return;
130 }
131 for (int i = 0; i < siteNames.length; i++) {
132 loadSite(siteNames[i]);
133 }
134 }
135
136 public void loadSite(String siteName) {
137 String path = TgwPathResolver.getSiteConfigFilePath(siteName);
138
139 DiconResource resource = new DiconResource();
140 resource.setPath(path);
141 resource.load();
142
143 if (resource.hasContainer()) {
144 SiteConfig siteConfig = (SiteConfig) resource
145 .getComponent(SiteConfig.class);
146 doCreateSite(siteConfig, false);
147 model.loadDomain(siteName);
148 helper.setupControllerConfigs(siteName);
149 logicService.loadLogics(siteName);
150 pluginService.loadExtPlugins(siteName);
151 helper.setupFileDataTable(siteName);
152 }
153 }
154
155 public void uploadSite(String siteName, JarInputStream jinput,
156 BackupDto backupDto) throws TgwServiceException {
157 ResourceUtils.readJar(jinput, Constants.DIRECTORY_APP);
158 loadSite(siteName);
159 restore(siteName, backupDto);
160
161 SiteConfig siteConfig = getSiteConfig(siteName);
162 siteConfig.setSkin(DesignService.ARCHIVE_SKIN_NAME);
163 saveSiteConfig(siteName);
164
165
166
167 updatePath(siteConfig,true);
168 }
169
170 public void downloadSite(String siteName, JarOutputStream jarout,
171 BackupDto backupDto) throws TgwServiceException {
172 String path = TgwPathResolver.getSiteDirectory(siteName);
173
174 String backupDate = backupDto.getBackupDate();
175 if (backupDate == null || "".equals(backupDate)) {
176 backupDto.setType(BackupDto.BACKUPTYPE_FULL);
177 backup(siteName, backupDto);
178 }
179
180 String siteBackupDir = siteName + "/backup";
181
182 ResourceUtils.writeJar(jarout, path, "", siteBackupDir);
183
184 ResourceUtils.writeJar(jarout, path + "/" + Constants.DIRECTORY_BACKUP
185 + backupDto.getBackupDate(), siteBackupDir, null);
186 }
187
188 public void setDefaultInitpageName(String defaultInitpageName) {
189 this.defaultInitpageName = defaultInitpageName;
190 }
191
192 public void setDefaultMenupageName(String defaultMenupageName) {
193 this.defaultMenupageName = defaultMenupageName;
194 }
195
196
197
198 private void doCreateSite(SiteConfig siteConfig, boolean initialize) {
199
200 String siteName = siteConfig.getName();
201
202 try {
203 if (siteConfig.getInitPagename() == null
204 || siteConfig.getInitPagename().equals("")) {
205 siteConfig.setInitPagename(defaultInitpageName);
206 }
207
208 if (siteConfig.getMenuPagename() == null
209 || siteConfig.getMenuPagename().equals("")) {
210 siteConfig.setMenuPagename(defaultMenupageName);
211 }
212
213 try{
214 contents.createSite(siteConfig);
215 }catch(TgwResourceAlreadyExistsException e){
216
217
218
219
220
221 }
222 controller.createSite(siteConfig);
223
224 if (!siteConfig.isUseBaseDatabase()) {
225 String dbName = siteConfig.getDbName();
226 String dbSchema = siteConfig.getDbSchema();
227 db.setExternalDatabaseMapping(siteName, dbName, dbSchema);
228 }
229 model.createDomain(siteName);
230
231 siteConfigMap.put(siteName, siteConfig);
232 siteConfigs.add(siteConfig);
233 if (initialize) {
234 initializeSite(siteConfig);
235 doSave(siteConfig);
236 }
237 updatePath(siteConfig, false);
238 loadSecurity(siteConfig);
239
240 } catch (TgwServiceException e) {
241
242 e.printStackTrace();
243 } catch (Exception e) {
244 e.printStackTrace();
245 throw new RuntimeException(e);
246 }
247 }
248
249 public void editSite(SiteConfig siteConfig) {
250 initSecurity(siteConfig);
251 loadSecurity(siteConfig);
252
253 SiteConfig oldSiteConfig = (SiteConfig) siteConfigMap.get(siteConfig
254 .getName());
255
256 oldSiteConfig.copySiteConfig(siteConfig);
257
258 doSave(siteConfig);
259
260 try {
261 designService.sync(siteConfig, false);
262 } catch (TgwServiceException tse) {
263 tse.printStackTrace();
264 throw new RuntimeException(tse);
265 }
266 }
267
268 public void saveSiteConfig(String siteName) {
269 SiteConfig siteConfig = getSiteConfig(siteName);
270 doSave(siteConfig);
271 }
272
273 public List getSiteConfigList() {
274 return siteConfigs;
275 }
276
277 public SiteConfig getSiteConfig(String siteName) {
278 return (SiteConfig) siteConfigMap.get(siteName);
279 }
280
281 public void backup(String siteName, BackupDto backupDto)
282 throws TgwServiceException {
283
284 String dateStr = Constants.SIMPLE_DATEFORMAT.format(new Date());
285 backupDto.setBackupDate(dateStr);
286 String backupDirectory = TgwPathResolver.getSiteBackupDirPath(siteName,
287 dateStr);
288
289 try {
290 if (backupDto.isIncludeContents()) {
291 contents.backup(siteName, backupDirectory);
292 }
293
294 if (backupDto.isIncludeDatabase()) {
295 SiteConfig siteConfig = getSiteConfig(siteName);
296 if (!siteConfig.isUseBaseDatabase()) {
297 db.backup(siteConfig.getDbName(), siteConfig.getDbSchema(),
298 backupDto.getTablenames(), backupDirectory);
299 } else {
300 db.backup(null, siteName, backupDto.getTablenames(),
301 backupDirectory);
302 }
303 }
304
305 backupSiteLocalDirectory(siteName, backupDirectory);
306 } catch (Exception e) {
307 log.error("failed to backup : " + e.getMessage());
308 e.printStackTrace();
309 ResourceUtils.removeContent(backupDirectory);
310 throw new TgwServiceException(e);
311 }
312 }
313
314 public List getBackupDates(String siteName) {
315 String backupDirectory = TgwPathResolver.getSiteBackupDirPath(siteName);
316 String[] names = ResourceUtils.getChildrenNames(backupDirectory);
317 if (names == null || names.length == 0) {
318 return null;
319 }
320
321 List dates = new ArrayList();
322 for (int i = 0; i < names.length; i++) {
323 BackupDto dto = retrieveBackupDto(siteName, names[i]);
324 dates.add(dto);
325 }
326 return dates;
327 }
328
329 public void restore(String siteName, BackupDto backupDto)
330 throws TgwServiceException {
331
332 String backupDirectory = TgwPathResolver.getSiteBackupDirPath(siteName,
333 backupDto.getBackupDate());
334 if (backupDirectory.endsWith(Constants.DIRECTORY_BACKUP)) {
335
336
337 String[] candidates = ResourceUtils
338 .getChildrenNames(backupDirectory);
339 if (candidates == null || candidates.length == 0) {
340 throw new TgwServiceException(
341 "No backup contents avaliable on local filesystem for restore.");
342 } else {
343 String candidate = candidates[candidates.length - 1];
344 backupDirectory = TgwPathResolver.getSiteBackupDirPath(
345 siteName, candidate);
346 backupDto.setBackupDate(candidate);
347 }
348 }
349
350 try {
351
352 setBackupType(backupDirectory, backupDto);
353
354 if (backupDto.isIncludeContents()) {
355 contents.restore(siteName, backupDirectory);
356 }
357
358 if (backupDto.isIncludeDatabase()) {
359 SiteConfig siteConfig = getSiteConfig(siteName);
360 if (!siteConfig.isUseBaseDatabase()) {
361 db.restore(siteConfig.getDbName(),
362 siteConfig.getDbSchema(), null, backupDirectory);
363 } else {
364 db.restore(null, siteName, null, backupDirectory);
365 }
366 }
367
368 if (!backupDto.isNone()) {
369 restoreSiteLocalDirectory(siteName, backupDirectory);
370 } else {
371 log
372 .warn("this archive doesn't include any valid backup data : "
373 + backupDirectory);
374 }
375
376 } catch (Exception e) {
377 log.error("failed to restore contents under " + backupDirectory
378 + " - " + e.getMessage());
379 throw new TgwServiceException(e);
380 }
381 }
382
383 public void deleteBackup(String siteName, BackupDto backupDto)
384 throws TgwServiceException {
385 String backupDirectory = TgwPathResolver.getSiteBackupDirPath(siteName,
386 backupDto.getBackupDate());
387 try {
388 ResourceUtils.removeContent(backupDirectory);
389 } catch (Exception e) {
390 throw new TgwServiceException(e);
391 }
392 }
393
394
395
396 public void setSecurity(String siteName, Action action, String roles) {
397 SiteConfig siteConfig = getSiteConfig(siteName);
398 String[] roleNames = SecurityUtils.splitRoleNames(roles);
399 if (SecurityUtils.hasUnauthenticated(roleNames)) {
400 siteConfig.putActionRoles(action, null);
401 } else {
402 siteConfig.putActionRoles(action, roles);
403 }
404 setActionRoles(siteName, action, roleNames);
405 }
406
407 public boolean hasPermission(String siteName, String role, Action action) {
408 SiteConfig siteConfig = getSiteConfig(siteName);
409 String[] roleNames = siteConfig.getRoleNames(action);
410 if (roleNames == null || roleNames.length < 1) {
411 return true;
412 }
413 return ArrayUtils.contains(roleNames, role);
414 }
415
416 public boolean hasPermission(String siteName, HttpServletRequest request,
417 Action action) {
418 SiteConfig siteConfig = getSiteConfig(siteName);
419 String[] roleNames = siteConfig.getRoleNames(action);
420 if (roleNames == null || roleNames.length < 1) {
421 return true;
422 }
423 for (int i = 0; i < roleNames.length; i++) {
424 if (request.isUserInRole(roleNames[i])) {
425 return true;
426 }
427 }
428 return false;
429 }
430
431 public boolean hasPermission(String siteName, Principal principal,
432 Action action) {
433 throw new UnsupportedOperationException();
434 }
435
436 public void updatePath(SiteConfig siteConfig, boolean isNeedCleanup)
437 throws TgwServiceException {
438
439 String siteName = siteConfig.getName();
440 String path = "/top";
441
442 if (isNeedCleanup) {
443 String[] forwardNames = controller.getForwardNames(siteName, path);
444 for (int i = 0; i < forwardNames.length; i++) {
445 String forwardName = forwardNames[i];
446 if (forwardName.endsWith("html")) {
447 controller.removeForwardPath(siteName, path, forwardName,
448 "/" + forwardName);
449 }
450 }
451 }
452
453 String[] skinPages = null;
454 if("archive".equals(siteConfig.getSkin())){
455 String realPath =
456 TgwContext.getRealPath(Constants.SITE_LOCAL_DIRECTORY + "/" + siteName);
457 File siteDir = new File(realPath);
458 skinPages = siteDir.list(new SuffixFileFilter(".html"));
459 }else{
460 DesignConfig designConfig =
461 designService.getDesignConfig(siteConfig.getSkin());
462 skinPages = designConfig.getAvailablePages();
463 }
464
465 if(skinPages != null){
466 for (int i = 0; i < skinPages.length; i++) {
467 String skinHtml = skinPages[i];
468 try {
469 controller.addForwardPath(siteName, path, skinHtml, "/"
470 + skinHtml);
471 } catch (TgwServiceException tse) {
472 log.warn("ignore " + skinHtml + " : " + tse.getMessage());
473 }
474 }
475 }
476
477 }
478
479 public void copySite(String srcSiteName, String destSiteName) throws TgwException{
480
481 BackupDto dto = getDatabaseBackupDto();
482
483 try{
484
485 backup(srcSiteName,dto);
486
487 String siteRoot = TgwPathResolver.getSiteDirectory("");
488 String srcPath = ResourceUtils.getFile(siteRoot + "/" + srcSiteName).getAbsolutePath();
489 String destPath = ResourceUtils.getFile(siteRoot).getAbsolutePath() + File.separator + destSiteName;
490
491
492 ResourceUtils.copyDirectory(srcPath,destPath);
493
494
495 SiteConfig siteConfig = new SiteConfig();
496 SiteConfig oldSiteConfig = (SiteConfig) siteConfigMap.get(srcSiteName);
497 copySiteConfig(oldSiteConfig,siteConfig);
498 siteConfig.setName(destSiteName);
499 doSave(siteConfig);
500
501
502 if(model.getDomain(srcSiteName) != null){
503 model.copyDomain(srcSiteName,destSiteName);
504 }
505
506
507 initializeSite(siteConfig);
508
509
510 contents.copySite(srcSiteName,destSiteName);
511
512
513 loadSite(destSiteName);
514
515
516 restore(destSiteName,dto);
517
518
519 String backupDirectory = TgwPathResolver.getSiteBackupDirPath(destSiteName,dto.getBackupDate());
520 String srcSiteLocalPath = ResourceUtils.getFile(backupDirectory + "/" + srcSiteName).getPath();
521 String destSiteLocalPath = ResourceUtils.getFile(backupDirectory + "/" + destSiteName).getPath();
522 ResourceUtils.copyDirectory(srcSiteLocalPath,destSiteLocalPath);
523
524 restoreSiteLocalDirectory(destSiteName,backupDirectory);
525 deleteBackup(destSiteName,dto);
526
527 }catch(Exception e){
528 throw new TgwException("ETGW4002",new Object[]{srcSiteName,destSiteName,e.getMessage()},e);
529 }
530 }
531
532
533
534 private String[] getSiteNames() {
535 return ResourceUtils.getChildrenNames(Constants.DIRECTORY_APP);
536 }
537
538 private void doSave(SiteConfig config) {
539 DiconResource resource = new DiconResource();
540 resource.addComponent(config);
541 resource.setPath(TgwPathResolver
542 .getSiteConfigFilePath(config.getName()));
543 resource.save();
544 }
545
546 private void loadSecurity(SiteConfig siteConfig) {
547 for (int i = 0; i < Action.ACTIONS.length; i++) {
548 Action action = Action.ACTIONS[i];
549 String[] roleNames = siteConfig.getRoleNames(action);
550 setActionRoles(siteConfig.getName(), action, roleNames);
551 }
552 }
553
554 private void initSecurity(SiteConfig siteConfig) {
555 if (!siteConfig.isSecurity()) {
556 return;
557 }
558
559 String[] roleNames = siteConfig.getRoleNames();
560 boolean unauthencticatedFlag = SecurityUtils
561 .hasUnauthenticated(roleNames);
562 roleNames = SecurityUtils.removeUnauthenticated(roleNames);
563 String roles = StringUtils.join(roleNames, ",");
564
565 for (int i = 0; i < Action.ACTIONS.length; i++) {
566 Action action = Action.ACTIONS[i];
567 if (!action.equals(Action.PAGE_VIEW) || !unauthencticatedFlag) {
568 siteConfig.putActionRoles(action, roles);
569 }
570 }
571 }
572
573 private void setActionRoles(String siteName, Action action,
574 String[] roleNames) {
575 boolean unauthencticatedFlag = SecurityUtils
576 .hasUnauthenticated(roleNames);
577 String roles = null;
578
579 if ((roleNames != null && roleNames.length == 0)
580 || unauthencticatedFlag) {
581 roles = "";
582 } else {
583 roleNames = SecurityUtils.removeUnauthenticated(roleNames);
584 roles = StringUtils.join(roleNames, ",");
585 }
586 controller.setActionRoles(siteName, action, roles);
587 }
588
589 private void createSiteLocalDirectory(String siteName) {
590 String urlpath = Constants.SITE_LOCAL_DIRECTORY + File.separator
591 + siteName;
592 String siteLocal = TgwContext.getRealPath(urlpath);
593 if (ResourceUtils.createDirectory(siteLocal)) {
594 log.info("create site local directory : " + siteLocal);
595 }
596 }
597
598 private void backupSiteLocalDirectory(String siteName,
599 String backupDirectory) throws IOException {
600 String path = TgwContext.getRealPath("/"
601 + Constants.SITE_LOCAL_DIRECTORY);
602 String srcPath = path + File.separator + siteName;
603 String destPath = ResourceUtils.getFile(backupDirectory).getPath();
604 ResourceUtils.copyFile(srcPath, destPath);
605 }
606
607 private void restoreSiteLocalDirectory(String siteName,
608 String backupDirectory) throws IOException {
609 String destPath = TgwContext.getRealPath("/"
610 + Constants.SITE_LOCAL_DIRECTORY);
611 String srcPath = ResourceUtils
612 .getFile(backupDirectory + "/" + siteName).getPath();
613 ResourceUtils.copyFile(srcPath, destPath);
614 }
615
616 private void deleteSiteLocalDirectory(String siteName) {
617 String path = TgwContext.getRealPath("/"
618 + Constants.SITE_LOCAL_DIRECTORY + "/" + siteName);
619 ResourceUtils.deleteDirectory(new File(path));
620 }
621
622 private BackupDto retrieveBackupDto(String siteName, String backupDate) {
623 String path = TgwPathResolver
624 .getSiteBackupDirPath(siteName, backupDate);
625 BackupDto dto = new BackupDto();
626 dto.setBackupDate(backupDate);
627 setBackupType(path, dto);
628 return dto;
629 }
630
631 private void setBackupType(String path, BackupDto dto) {
632
633 boolean isTableBackuped = ResourceUtils.isExist(path + "table.dicon");
634 boolean isPageBackuped = ResourceUtils.isExist(path + "webdav");
635
636 if (isTableBackuped && isPageBackuped) {
637 dto.setType(BackupDto.BACKUPTYPE_FULL);
638 } else if (isTableBackuped && !isPageBackuped) {
639 dto.setType(BackupDto.BACKUPTYPE_DATABASE);
640 } else if (!isTableBackuped && isPageBackuped) {
641 dto.setType(BackupDto.BACKUPTYPE_PAGE);
642 } else {
643 dto.setType(BackupDto.BACKUPTYPE_NONE);
644 }
645 }
646
647 private BackupDto getDatabaseBackupDto(){
648 BackupDto dto = new BackupDto();
649 dto.setType(BackupDto.BACKUPTYPE_DATABASE);
650 return dto;
651 }
652
653 private void copySiteConfig(SiteConfig srcSiteConfig, SiteConfig destSiteConfig){
654
655 destSiteConfig.setName(srcSiteConfig.getName());
656 destSiteConfig.setTitle(srcSiteConfig.getTitle());
657 destSiteConfig.setDescription(srcSiteConfig.getDescription());
658 destSiteConfig.setRoles(srcSiteConfig.getRoles());
659 destSiteConfig.setEasyMode(srcSiteConfig.isEasyMode());
660 destSiteConfig.setPageEditMode(srcSiteConfig.getPageEditMode());
661 destSiteConfig.setSkin(srcSiteConfig.getSkin());
662 destSiteConfig.setUseBaseDatabase(srcSiteConfig.isUseBaseDatabase());
663 destSiteConfig.setDbName(srcSiteConfig.getDbName());
664 destSiteConfig.setDbSchema(srcSiteConfig.getDbSchema());
665
666 Map map = srcSiteConfig.getActionRolesMap();
667 if(map != null){
668 for(Iterator i=map.keySet().iterator();i.hasNext();){
669 String actionName = (String)i.next();
670 destSiteConfig.putActionRoles(actionName,(String)map.get(actionName));
671 }
672 }
673 }
674
675 private void initializeSite(SiteConfig siteConfig) throws TgwServiceException{
676
677 String siteName = siteConfig.getName();
678 createSiteLocalDirectory(siteName);
679 if (!siteConfig.isUseBaseDatabase()) {
680 List list = model.readDatabase(siteName);
681 controller.addEntityConfigs(list);
682 }
683 designService.sync(siteConfig,false);
684 initSecurity(siteConfig);
685 }
686
687 }