Java tutorial
/* * Copyright 2006 The National Library of New Zealand * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.webcurator.ui.target.controller; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.text.NumberFormat; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Iterator; import java.util.Locale; import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.propertyeditors.CustomNumberEditor; import org.springframework.context.MessageSource; import org.springframework.validation.BindException; import org.springframework.web.bind.ServletRequestDataBinder; import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.multipart.commons.CommonsMultipartFile; import org.springframework.web.multipart.support.ByteArrayMultipartFileEditor; import org.springframework.web.servlet.ModelAndView; import org.webcurator.auth.AuthorityManager; import org.webcurator.core.permissionmapping.PermissionMappingStrategy; import org.webcurator.core.permissionmapping.UrlUtils; import org.webcurator.core.targets.TargetManager; import org.webcurator.domain.Pagination; import org.webcurator.domain.model.auth.Privilege; import org.webcurator.domain.model.core.BusinessObjectFactory; import org.webcurator.domain.model.core.Permission; import org.webcurator.domain.model.core.PermissionExclusion; import org.webcurator.domain.model.core.Seed; import org.webcurator.domain.model.core.Target; import org.webcurator.ui.common.Constants; import org.webcurator.ui.target.TargetEditorContext; import org.webcurator.ui.target.command.SeedsCommand; import org.webcurator.ui.target.validator.TargetSeedsValidator; import org.webcurator.ui.util.Tab; import org.webcurator.ui.util.TabbedController; import org.webcurator.ui.util.TabbedController.TabbedModelAndView; /** * The handler for the target seeds handler. * @author bbeaumont */ public class TargetSeedsHandler extends AbstractTargetTabHandler { private static Log log = LogFactory.getLog(TargetSeedsHandler.class); private BusinessObjectFactory businessObjectFactory = null; private TargetManager targetManager = null; private TargetSeedsValidator validator = null; private AuthorityManager authorityManager = null; private MessageSource messageSource = null; @Override public void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception { // Determine the necessary formats. NumberFormat nf = NumberFormat.getInstance(request.getLocale()); // Register the binders. binder.registerCustomEditor(Long.class, new CustomNumberEditor(Long.class, nf, true)); // to actually be able to convert Multipart instance to byte[] // we have to register a custom editor (in this case the // ByteArrayMultipartEditor binder.registerCustomEditor(byte[].class, new ByteArrayMultipartFileEditor()); // now Spring knows how to handle multipart object and convert them } /* (non-Javadoc) * @see org.webcurator.ui.util.TabHandler#processTab(org.webcurator.ui.util.TabbedController, org.webcurator.ui.util.Tab, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, org.springframework.validation.BindException) */ public void processTab(TabbedController tc, Tab currentTab, HttpServletRequest req, HttpServletResponse res, Object comm, BindException errors) { // Do nothing. } /* (non-Javadoc) * @see org.webcurator.ui.util.TabHandler#preProcessNextTab(org.webcurator.ui.util.TabbedController, org.webcurator.ui.util.Tab, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, org.springframework.validation.BindException) */ public TabbedModelAndView preProcessNextTab(TabbedController tc, Tab nextTabID, HttpServletRequest req, HttpServletResponse res, Object comm, BindException errors) { TabbedModelAndView tmav = tc.new TabbedModelAndView(); TargetEditorContext ctx = getEditorContext(req); List<Seed> seeds = ctx.getSortedSeeds(); tmav.addObject("seeds", seeds); tmav.addObject("quickPicks", ctx.getQuickPickPermissions()); tmav.addObject("allowMultiplePrimarySeeds", targetManager.getAllowMultiplePrimarySeeds()); return tmav; } private boolean mapSeed(TargetEditorContext ctx, Seed aSeed, long mappingOption) throws SeedLinkWrongAgencyException { // Automatic mapping. if (mappingOption == SeedsCommand.PERM_MAPPING_AUTO) { Set<Permission> permissions = PermissionMappingStrategy.getStrategy() .getMatchingPermissions(ctx.getTarget(), aSeed); // Make sure our linked permissions are in our context cache. Set<Permission> toLink = new HashSet<Permission>(); for (Permission p : permissions) { ctx.putObject(p); toLink.add(p); } //aSeed.setPermissions(toLink); return linkSeed(ctx.getTarget(), aSeed, toLink); } // Map to nothing else if (mappingOption == SeedsCommand.PERM_MAPPING_NONE) { // Don't set any permissions. return false; } // Map to a quick pick. else { Permission quickPick = (Permission) ctx.getObject(Permission.class, mappingOption); //aSeed.addPermission(quickPick); return linkSeed(ctx.getTarget(), aSeed, quickPick); } } /** * * @param aTarget The target that is being linked. * @param aSeed The seed. * @param aPermission The permisison. * @return true if any exclusions have been added. */ private boolean linkSeed(Target aTarget, Seed aSeed, Permission aPermission) throws SeedLinkWrongAgencyException { if (!aPermission.getOwningAgency().equals(aTarget.getOwningUser().getAgency())) { throw new SeedLinkWrongAgencyException(); } else { aSeed.addPermission(aPermission); if (aPermission.getExclusions().size() > 0) { aTarget.getOverrides().setOverrideExcludeUriFilters(true); for (PermissionExclusion excl : aPermission.getExclusions()) { if (!aTarget.getOverrides().getExcludeUriFilters().contains(excl.getUrl())) { aTarget.getOverrides().getExcludeUriFilters().add(excl.getUrl()); } } } return aPermission.getExclusions().size() > 0; } } /** * * @param aTarget The target that is being linked. * @param aPermission The permisison. * @param aSeed The seed. * @return true if any exclusions have been added. */ private boolean linkSeed(Target aTarget, Seed aSeed, Set<Permission> aPermissionList) throws SeedLinkWrongAgencyException { boolean exclusionsAdded = false; for (Permission p : aPermissionList) { exclusionsAdded = linkSeed(aTarget, aSeed, p) | exclusionsAdded; } return exclusionsAdded; } private boolean isSelected(HttpServletRequest req, Seed seed) { String onOff = (req.getParameterValues("chkSelect" + seed.getIdentity()) != null) ? req.getParameterValues("chkSelect" + seed.getIdentity())[0] : "off"; return onOff.equals("on"); } /* (non-Javadoc) * @see org.webcurator.ui.util.TabHandler#processOther(org.webcurator.ui.util.TabbedController, org.webcurator.ui.util.Tab, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, org.springframework.validation.BindException) */ public ModelAndView processOther(TabbedController tc, Tab currentTab, HttpServletRequest req, HttpServletResponse res, Object comm, BindException errors) { SeedsCommand command = (SeedsCommand) comm; TargetEditorContext ctx = getEditorContext(req); if (authorityManager.hasAtLeastOnePrivilege(ctx.getTarget(), Privilege.MODIFY_TARGET, Privilege.CREATE_TARGET)) { if (command.isAction(SeedsCommand.ACTION_ADD)) { if (errors.hasErrors()) { // Go to the Seeds tab. TabbedModelAndView tmav = preProcessNextTab(tc, currentTab, req, res, comm, errors); tmav.addObject(Constants.GBL_CMD_DATA, command); tmav.getTabStatus().setCurrentTab(currentTab); return tmav; } else { // Create the seed business object. Seed seed = businessObjectFactory.newSeed(ctx.getTarget()); seed.setSeed(command.getSeed().trim()); //remove any trailing spaces // Set the first seed to be primary, others to be secondary. seed.setPrimary(ctx.getTarget().getSeeds().size() == 0); // Associate with the correct permissions. long option = command.getPermissionMappingOption().longValue(); boolean addedExclusions = false; try { addedExclusions = mapSeed(ctx, seed, option); ctx.putObject(seed); ctx.getTarget().addSeed(seed); } // The seed we've tried to link to is from a different // agency. catch (SeedLinkWrongAgencyException ex) { errors.reject("target.seeds.link.wrong_agency", new Object[] {}, "One of the selected seeds cannot be linked because it belongs to another agency."); } // Go to the Seeds tab. TabbedModelAndView tmav = preProcessNextTab(tc, currentTab, req, res, comm, errors); tmav.getTabStatus().setCurrentTab(currentTab); if (addedExclusions) { tmav.addObject(Constants.GBL_MESSAGES, messageSource .getMessage("target.linkseeds.exclusions", new Object[] {}, Locale.getDefault())); } return tmav; } } if (command.isAction(SeedsCommand.ACTION_REMOVE)) { // Remove the URL. Seed seedToRemove = (Seed) ctx.getObject(Seed.class, command.getSelectedSeed()); ctx.getTarget().removeSeed(seedToRemove); // Go back to the URLs tab. TabbedModelAndView tmav = preProcessNextTab(tc, currentTab, req, res, comm, errors); tmav.getTabStatus().setCurrentTab(currentTab); return tmav; } if (command.isAction(SeedsCommand.ACTION_REMOVE_SELECTED)) { // Remove the selected URLs. Set<Seed> seeds = ctx.getTarget().getSeeds(); Set<Seed> seedsToRemove = new HashSet<Seed>(); Iterator<Seed> it = seeds.iterator(); while (it.hasNext()) { Seed seed = it.next(); if (isSelected(req, seed)) { seedsToRemove.add(seed); } } it = seedsToRemove.iterator(); while (it.hasNext()) { Seed seedToRemove = it.next(); ctx.getTarget().removeSeed(seedToRemove); } // Go back to the URLs tab. TabbedModelAndView tmav = preProcessNextTab(tc, currentTab, req, res, comm, errors); tmav.getTabStatus().setCurrentTab(currentTab); return tmav; } if (command.isAction(SeedsCommand.ACTION_TOGGLE_PRIMARY)) { Seed seed = (Seed) ctx.getObject(Seed.class, command.getSelectedSeed()); if (targetManager.getAllowMultiplePrimarySeeds()) { //toggle the selected seed seed.setPrimary(!seed.isPrimary()); } else { //Reset all seeds to not primary List<Seed> seeds = ctx.getSortedSeeds(); Iterator<Seed> it = seeds.iterator(); while (it.hasNext()) { Seed listItem = it.next(); listItem.setPrimary(false); } //Set the selected seed to primary seed.setPrimary(true); } // Go back to the URLs tab. TabbedModelAndView tmav = preProcessNextTab(tc, currentTab, req, res, comm, errors); tmav.getTabStatus().setCurrentTab(currentTab); return tmav; } if (command.isAction(SeedsCommand.ACTION_UNLINK)) { Seed seed = (Seed) ctx.getObject(Seed.class, command.getSelectedSeed()); Permission permission = (Permission) ctx.getObject(Permission.class, command.getSelectedPermission()); seed.removePermission(permission); // Go back to the URLs tab. TabbedModelAndView tmav = preProcessNextTab(tc, currentTab, req, res, comm, errors); tmav.getTabStatus().setCurrentTab(currentTab); return tmav; } if (command.isAction(SeedsCommand.ACTION_UNLINK_SELECTED)) { //Unlink all permissions from the selected seeds Set<Seed> seeds = ctx.getTarget().getSeeds(); Iterator<Seed> it = seeds.iterator(); while (it.hasNext()) { Seed seed = it.next(); if (isSelected(req, seed)) { Set<Permission> permissions = seed.getPermissions(); permissions.clear(); seed.getTarget().setDirty(true); } } // Go back to the URLs tab. TabbedModelAndView tmav = preProcessNextTab(tc, currentTab, req, res, comm, errors); tmav.getTabStatus().setCurrentTab(currentTab); return tmav; } if (command.isAction(SeedsCommand.ACTION_LINK_NEW)) { SeedsCommand newCommand = new SeedsCommand(); Seed selectedSeed = (Seed) ctx.getObject(Seed.class, command.getSelectedSeed()); newCommand.setSelectedSeed(command.getSelectedSeed()); newCommand.setSearchType(SeedsCommand.SEARCH_URL); newCommand.setUrlSearchCriteria(selectedSeed.getSeed()); boolean doSearch = validator.validateLinkSearch(command, errors); return processLinkSearch(tc, ctx.getTarget(), newCommand, doSearch, errors); } if (command.isAction(SeedsCommand.ACTION_LINK_SELECTED)) { //Unlink all permissions from the selected seeds Set<Seed> seeds = ctx.getTarget().getSeeds(); Set<Seed> selectedSeeds = new HashSet<Seed>(); String seedList = ""; Iterator<Seed> it = seeds.iterator(); while (it.hasNext()) { Seed seed = it.next(); if (isSelected(req, seed)) { selectedSeeds.add(seed); if (seedList.isEmpty()) { seedList = seed.getIdentity(); } else { seedList += "," + seed.getIdentity(); } } } if (selectedSeeds.size() > 0) { SeedsCommand newCommand = new SeedsCommand(); newCommand.setSelectedSeed(seedList); newCommand.setSearchType(SeedsCommand.SEARCH_SITES); newCommand.setSiteSearchCriteria(""); ctx.putAllObjects(selectedSeeds); return processLinkSearch(tc, ctx.getTarget(), newCommand, false, errors); } else { // Go back to the URLs tab. TabbedModelAndView tmav = preProcessNextTab(tc, currentTab, req, res, comm, errors); tmav.getTabStatus().setCurrentTab(currentTab); return tmav; } } if (command.isAction(SeedsCommand.ACTION_LINK_NEW_SEARCH)) { if (errors.hasErrors()) { return processLinkSearch(tc, ctx.getTarget(), command, false, errors); } else { SeedsCommand newCommand = new SeedsCommand(); newCommand.setSelectedSeed(command.getSelectedSeed()); newCommand.setSearchType(command.getSearchType()); newCommand.setSiteSearchCriteria(command.getSiteSearchCriteria()); newCommand.setUrlSearchCriteria(command.getUrlSearchCriteria()); newCommand.setPageNumber(command.getPageNumber()); return processLinkSearch(tc, ctx.getTarget(), newCommand, true, errors); } } if (command.isAction(SeedsCommand.ACTION_LINK_NEW_CONFIRM)) { if (errors.hasErrors()) { boolean doSearch = validator.validateLinkSearch(command, errors); return processLinkSearch(tc, ctx.getTarget(), command, doSearch, errors); } else { // Go back to the URLs tab. TabbedModelAndView tmav = preProcessNextTab(tc, currentTab, req, res, comm, errors); tmav.getTabStatus().setCurrentTab(currentTab); // Get the selected seed(s). String[] seedList = command.getSelectedSeed().split(","); for (int s = 0; s < seedList.length; s++) { Seed theSeed = (Seed) ctx.getObject(Seed.class, seedList[s]); // Link all the selected permissions. String[] perms = command.getLinkPermIdentity(); Set<Permission> toLink = new HashSet<Permission>(); boolean wrongAgencyPermission = false; for (int i = 0; i < perms.length && !wrongAgencyPermission; i++) { Permission linkPerm = targetManager.loadPermission(ctx, perms[i]); toLink.add(linkPerm); if (!linkPerm.getOwningAgency().equals(ctx.getTarget().getOwner().getAgency())) { wrongAgencyPermission = true; } } try { boolean addedExclusions = linkSeed(ctx.getTarget(), theSeed, toLink); if (addedExclusions) { tmav.addObject(Constants.GBL_MESSAGES, messageSource.getMessage( "target.linkseeds.exclusions", new Object[] {}, Locale.getDefault())); } } catch (SeedLinkWrongAgencyException ex) { errors.reject("target.seeds.link.wrong_agency", new Object[] {}, "One of the selected seeds cannot be linked because it belongs to another agency."); boolean doSearch = validator.validateLinkSearch(command, errors); return processLinkSearch(tc, ctx.getTarget(), command, doSearch, errors); } } return tmav; } } if (command.isAction(SeedsCommand.ACTION_LINK_NEW_CANCEL)) { // Go back to the URLs tab. TabbedModelAndView tmav = preProcessNextTab(tc, currentTab, req, res, comm, errors); tmav.getTabStatus().setCurrentTab(currentTab); return tmav; } if (command.isAction(SeedsCommand.ACTION_START_IMPORT)) { return getImportSeedsTabModel(tc, ctx); } if (command.isAction(SeedsCommand.ACTION_DO_IMPORT)) { BufferedReader reader = null; MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) req; CommonsMultipartFile file = (CommonsMultipartFile) multipartRequest.getFile("seedsFile"); if (command.getSeedsFile().length == 0 || file.getOriginalFilename() == null || "".equals(file.getOriginalFilename().trim())) { errors.reject("target.seeds.import.nofile"); TabbedModelAndView tmav = getImportSeedsTabModel(tc, ctx); tmav.addObject(Constants.GBL_ERRORS, errors); return tmav; } if (!file.getOriginalFilename().endsWith(".txt") && !"text/plain".equals(file.getContentType())) { errors.reject("target.seeds.import.filetype"); TabbedModelAndView tmav = getImportSeedsTabModel(tc, ctx); tmav.addObject(Constants.GBL_ERRORS, errors); return tmav; } else { try { reader = new BufferedReader( new InputStreamReader(new ByteArrayInputStream(command.getSeedsFile()))); List<Seed> validSeeds = new LinkedList<Seed>(); boolean success = true; int lineNumber = 1; String line = reader.readLine(); SeedsCommand importCommand = new SeedsCommand(); while (success && line != null) { if (!line.startsWith("#") && !"".equals(line.trim())) { Seed seed = businessObjectFactory.newSeed(ctx.getTarget()); importCommand.setSeed(line); seed.setSeed(importCommand.getSeed()); if (UrlUtils.isUrl(seed.getSeed())) { mapSeed(ctx, seed, command.getPermissionMappingOption()); // Update the target. ctx.putObject(seed); validSeeds.add(seed); } else { success = false; } } if (success) { line = reader.readLine(); lineNumber++; } } if (success) { for (Seed seed : validSeeds) { ctx.getTarget().addSeed(seed); } } else { errors.reject("target.seeds.import.badline", new Object[] { lineNumber }, "Bad seed detected on line: " + lineNumber); } } catch (SeedLinkWrongAgencyException ex) { errors.reject("target.seeds.link.wrong_agency", new Object[] {}, "One of the selected seeds cannot be linked because it belongs to another agency."); } catch (IOException ex) { errors.reject("target.seeds.import.ioerror"); log.error("Failed to import seeds", ex); } finally { try { reader.close(); } catch (Exception ex) { log.debug("Failed to close uploaded seeds file", ex); } } if (errors.hasErrors()) { TabbedModelAndView tmav = getImportSeedsTabModel(tc, ctx); tmav.addObject(Constants.GBL_ERRORS, errors); return tmav; } else { // Go back to the URLs tab. TabbedModelAndView tmav = preProcessNextTab(tc, currentTab, req, res, comm, errors); tmav.getTabStatus().setCurrentTab(currentTab); return tmav; } } } } if (command.isAction(SeedsCommand.ACTION_SET_NAME)) { String id = command.getUpdatedNameSeedId(); if (id != null) { for (Seed seed : ctx.getSortedSeeds()) { if (seed.getOid().equals(Long.valueOf(id))) { String value = command.getUpdatedNameSeedValue(); if (value.trim().equals("")) { errors.reject("target.seeds.name.edit.required"); TabbedModelAndView tmav = preProcessNextTab(tc, currentTab, req, res, comm, errors); tmav.addObject(Constants.GBL_CMD_DATA, command); tmav.getTabStatus().setCurrentTab(currentTab); return tmav; } if (UrlUtils.isUrl(seed.getSeed())) { seed.setSeed(UrlUtils.fixUrl(value)); ctx.putObject(seed); } else { errors.reject("target.seeds.name.edit.invalid"); TabbedModelAndView tmav = preProcessNextTab(tc, currentTab, req, res, comm, errors); tmav.addObject(Constants.GBL_CMD_DATA, command); tmav.getTabStatus().setCurrentTab(currentTab); return tmav; } System.out.println("Found seed " + id); } } } } TabbedModelAndView tmav = preProcessNextTab(tc, currentTab, req, res, comm, errors); tmav.getTabStatus().setCurrentTab(currentTab); return tmav; } public ModelAndView processLinkSearch(TabbedController tc, Target aTarget, SeedsCommand command, boolean doSearch, BindException errors) { TabbedModelAndView tmav = getSeedLinkTabModel(tc); tmav.addObject(Constants.GBL_CMD_DATA, command); if (doSearch) { Pagination results = null; if (SeedsCommand.SEARCH_SITES.equals(command.getSearchType())) { results = targetManager.findPermissionsBySiteTitle(aTarget, command.getSiteSearchCriteria(), command.getPageNumber()); } else { results = targetManager.findPermissionsByUrl(aTarget, command.getUrlSearchCriteria(), command.getPageNumber()); } tmav.addObject("results", results); } tmav.addObject(Constants.GBL_ERRORS, errors); return tmav; } private TabbedModelAndView getSeedLinkTabModel(TabbedController controller) { Tab tab = controller.getTabConfig().getTabByID("SEEDS").createSubTab("../target-seeds-link.jsp"); TabbedModelAndView tmav = controller.new TabbedModelAndView(); tmav.getTabStatus().setCurrentTab(tab); tmav.getTabStatus().setEnabled(false); return tmav; } private TabbedModelAndView getImportSeedsTabModel(TabbedController controller, TargetEditorContext ctx) { Tab tab = controller.getTabConfig().getTabByID("SEEDS").createSubTab("../target-seeds-import.jsp"); tab.setFormEncodingType("multipart/form-data"); TabbedModelAndView tmav = controller.new TabbedModelAndView(); tmav.getTabStatus().setCurrentTab(tab); tmav.getTabStatus().setEnabled(false); tmav.addObject("quickPicks", ctx.getQuickPickPermissions()); return tmav; } /** * @param businessObjectFactory The businessObjectFactory to set. */ public void setBusinessObjectFactory(BusinessObjectFactory businessObjectFactory) { this.businessObjectFactory = businessObjectFactory; } /** * @param targetManager The targetManager to set. */ public void setTargetManager(TargetManager targetManager) { this.targetManager = targetManager; } /** * @param validator The validator to set. */ public void setValidator(TargetSeedsValidator validator) { this.validator = validator; } /** * @param authorityManager The authorityManager to set. */ public void setAuthorityManager(AuthorityManager authorityManager) { this.authorityManager = authorityManager; } /** * @param messageSource The messageSource to set. */ public void setMessageSource(MessageSource messageSource) { this.messageSource = messageSource; } }