Java tutorial
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package de.fiz.ddb.aas.auxiliaryoperations; import java.io.IOException; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.logging.Level; import javax.naming.NameAlreadyBoundException; import javax.naming.NameNotFoundException; import javax.naming.NamingException; import javax.naming.directory.Attributes; import javax.naming.directory.BasicAttribute; import javax.naming.directory.BasicAttributes; import javax.naming.directory.InitialDirContext; import javax.naming.ldap.InitialLdapContext; import org.apache.commons.lang.StringUtils; import de.fiz.ddb.aas.administration.AasPrincipal; import de.fiz.ddb.aas.administration.ConstEnumOrgStatus; import de.fiz.ddb.aas.administration.Constants; import de.fiz.ddb.aas.administration.Organisation; import de.fiz.ddb.aas.authentication.Action; import de.fiz.ddb.aas.authorization.PrivilegeEnum; import de.fiz.ddb.aas.authorization.Scope; import de.fiz.ddb.aas.auxiliaryobjects.Email; import de.fiz.ddb.aas.auxiliaryobjects.OIDs; import de.fiz.ddb.aas.exceptions.AASUnauthorizedException; import de.fiz.ddb.aas.security.Authorizable; import de.fiz.ddb.aas.security.PreAuthorize; import de.fiz.ddb.aas.utils.JsonPropertiesSerializer; import de.fiz.ddb.aas.utils.LDAPEngineUtilityOrganisation; import de.fiz.ddb.aas.utils.PropertiesSerializer; import de.fiz.ddb.geocoding.GeoAdresse; import de.fiz.ddb.geocoding.GeoLocationType; import de.fiz.ddb.geocoding.GeoRequest; import de.fiz.ddb.geocoding.GeoRequestStatus; import de.fiz.ddb.ldap.connector.LDAPConnector; /** * * @author bk */ public class ThreadOrganisationCreate extends LDAPEngineUtilityOrganisation implements Callable<Organisation>, Authorizable { private Boolean _addToLicensedOrgs = null; private Boolean _ingestingOperation = null; private CountDownLatch _ready = null; private Organisation _orgObj = null; private AasPrincipal _performer = null; private OIDs _orgParentOIDs = null; private Future<GeoAdresse> _submit = null; private PropertiesSerializer serializer = new JsonPropertiesSerializer(); // *************************************************************************** private ThreadOrganisationCreate(AasPrincipal pPerformer) { this._performer = pPerformer; if (pPerformer == null) { throw new IllegalArgumentException("The contractor is unknown: Performer == null"); } } public ThreadOrganisationCreate(Organisation pOrgObj, AasPrincipal pPerformer) throws IllegalArgumentException, ExecutionException { this(pPerformer); // check mandatory fields if ((pOrgObj == null) || (pOrgObj.getOIDs() == null) || (pOrgObj.getId() == null)) { throw new IllegalArgumentException( "failed for add organization: the organization is unknown: Organisation = " + pOrgObj); } if ((pOrgObj.getDisplayName() == null) || (pOrgObj.getDisplayName().length() == 0)) { throw new IllegalArgumentException( "Failed for add organization: Mandatory field displayName may not be empty or null"); } // check fundingAgency: if ((pOrgObj.getOrgParent() != null) && (pOrgObj.getOrgParent().trim().length() > 0) && (pOrgObj.getFundingAgency() != null) && (pOrgObj.getFundingAgency().trim().length() > 0)) { throw new IllegalArgumentException( "The atrribut 'FundingAgency' for sub-organizations is not permitted"); } // check eMail if (StringUtils.isNotBlank(pOrgObj.getEmail())) { new Email(pOrgObj.getEmail()); } this._orgObj = pOrgObj; } /** * * @param pReadyLatch * : CountDownLatch, * @param pOrganisation * @param pPerformer * @throws IllegalArgumentException */ public ThreadOrganisationCreate(CountDownLatch pReadyLatch, Organisation pOrganisation, AasPrincipal pPerformer) throws AssertionError, IllegalArgumentException, ExecutionException { this(pOrganisation, pPerformer); this._ready = pReadyLatch; } // *************************************************************************** /** * * @return Organisation * @throws AASUnauthorizedException * @throws NamingException * @throws IOException * @throws CloneNotSupportedException * @throws IllegalAccessException * @throws Exception */ @PreAuthorize(privileges = { PrivilegeEnum.DEFAULT }, scope = Scope.ORGANIZATION) public Organisation call() throws AASUnauthorizedException, ExecutionException, NameAlreadyBoundException { Organisation vResult = this._orgObj; // -- Fr eine Prfung, ob bereits existent: // but only if that is not a copy in the export directory if (!this.isAddToLicensedOrgs() && organizationExists(this._orgObj.getOIDs().getOrgName())) { throw new NameAlreadyBoundException( "Error: A organization with ID: '" + this._orgObj.getOIDs().getOrgName() + "' already exists!"); } try { // -- Ist ein Parent bekannt, muss auch die komplette RDN aufgebaut // werden: if (!this.isAddToLicensedOrgs()) { if ((this._orgObj.getOrgRDN() == null) && (this._orgObj.getOrgParent() != null) && (!this._orgObj.getOrgParent().isEmpty())) { ThreadOIDsRDNComplement threadOIDsRDNComplement = new ThreadOIDsRDNComplement( new OIDs(this._orgObj.getOrgParent(), false), getPerformer()); this._orgParentOIDs = threadOIDsRDNComplement.call(); if (this._orgParentOIDs != null) { LOG.info("OrgParent = " + this._orgParentOIDs); this._orgObj.setOrgRDN(new StringBuilder(this._orgObj.getId()).append(",") .append(this._orgParentOIDs.getOrgRDN()).toString()); } else { throw new IllegalArgumentException("Error: A parent organization with ID: '" + this._orgObj.getOrgParent() + "' not found!"); } } else { this._orgObj.setOrgRDN(this._orgObj.getId()); } } // -- Ask about Geo coordinates but only if that is not a copy in the export directory or Licensed directory if (!this.isAddToLicensedOrgs() && !this.isIngestingOperation()) { boolean vQueryRequestForGeocoding = ((Math.abs(this._orgObj.getAddress().getLatitude()) <= 1e-6) || (Math.abs(this._orgObj.getAddress().getLongitude()) <= 1e-6)); if (vQueryRequestForGeocoding) { try { GeoRequest vGeoRequest = new GeoRequest(new GeoAdresse(this._orgObj.getAddress()), LDAPConnector.getSingletonInstance().getHttpProxy()); vGeoRequest.setAskForLocation(true); // -- should be set by Properties... change it! vGeoRequest.addAcceptLocationType(GeoLocationType.ROOFTOP, GeoLocationType.RANGE_INTERPOLATED, GeoLocationType.GEOMETRIC_CENTER, GeoLocationType.APPROXIMATE); _submit = LDAPConnector.getSingletonInstance().getExecutorServiceOne().submit(vGeoRequest); } catch (IllegalAccessException ex) { LOG.log(Level.SEVERE, "Error bei Adresse: " + this._orgObj.getAddress(), ex); } } } this.createOrg(); vResult = this._orgObj; // -- The performer gets automatically a member of this organization // X but only if that is not a copy in the export or licensed directory if ((!this.isAddToLicensedOrgs()) && (this._performer != null)) { //if ((this._performer != null)) { Map<OIDs, Set<PrivilegeEnum>> privileges = new HashMap<OIDs, Set<PrivilegeEnum>>(); privileges.put(this._orgObj.getOIDs(), new HashSet<PrivilegeEnum>()); privileges.get(this._orgObj.getOIDs()).add(PrivilegeEnum.ADMIN_ORG); ThreadUserOrgPrivilegsOperations threadUserOrgPrivilegsOperations = new ThreadUserOrgPrivilegsOperations( _performer.getUid(), privileges, Action.ADD, this._performer); threadUserOrgPrivilegsOperations.call(); } } catch (ExecutionException ex) { LOG.log(Level.WARNING, ex.getMessage(), ex.getCause()); throw ex; } catch (NameNotFoundException ex) { LOG.log(Level.SEVERE, ex.getMessage()); throw new ExecutionException(ex.getMessage(), ex); } catch (AssertionError ex) { LOG.log(Level.SEVERE, ex.getMessage()); throw new ExecutionException(ex.getMessage(), ex); } finally { if (this._ready != null) { this._ready.countDown(); } if ((_submit != null) && (!_submit.isDone()) && (!_submit.isCancelled())) { _submit.cancel(true); } } return vResult; } // *************************************************************************** private void createOrg() throws ExecutionException, IllegalArgumentException, AASUnauthorizedException { InitialLdapContext vCtx = null; Attributes vOrgAttributes = new BasicAttributes(true); BasicAttribute objectClass = new BasicAttribute("objectclass", "top"); objectClass.add(Constants.ldap_ddbOrg_ObjectClass); objectClass.add("organization"); vOrgAttributes.put(objectClass); // ---All this occurs only if that is not a copy in the export directory if (!this.isAddToLicensedOrgs()) { // -- When creating the status always set on Pending: if (!this.isIngestingOperation()) { this._orgObj.setStatus(ConstEnumOrgStatus.pending); long vTimeStamp = new Date().getTime(); this._orgObj.setModified(vTimeStamp); this._orgObj.setCreated(vTimeStamp); } if (this._performer != null) { this._orgObj.setModifiedBy(this._performer.getUid()); this._orgObj.setCreatedBy(this._performer.getUid()); } // -- Is null, if it was isIngestingOperation or isAddToLicensedOrgs // and therefore does not need to be additionally checked if (_submit != null) { GeoAdresse vGeoAdresse; try { vGeoAdresse = _submit.get(50, TimeUnit.SECONDS); if (vGeoAdresse.getRequestStatus() == GeoRequestStatus.OK) { this._orgObj.getAddress().setLatitude(vGeoAdresse.getLatitude()); this._orgObj.getAddress().setLongitude(vGeoAdresse.getLongitude()); this._orgObj.getAddress().setLocationDisplayName(vGeoAdresse.getLocationDisplayName()); } else { LOG.log(Level.WARNING, "GeoRequestStatus: {0}, (organization id: {1})", new Object[] { vGeoAdresse.getRequestStatus(), this._orgObj.getOIDs() }); } } catch (InterruptedException ex) { LOG.log(Level.WARNING, "Geocoding request exeption for organization id: " + this._orgObj.getOIDs(), ex); } catch (TimeoutException ex) { LOG.log(Level.WARNING, "Geocoding request exeption for organization id: " + this._orgObj.getOIDs(), ex); } } } // -- Conversion of parameters to LDAP attributes: this.convertOrganizationToLdapOrgAttrsForCreate(this._orgObj, vOrgAttributes, getPerformer()); StringBuilder vEntryDN = (this.isAddToLicensedOrgs() ? this.getLicensedOrgsDN(this._orgObj.getOIDs()) : this.getOrgDN(this._orgObj.getOIDs())); try { // put arbitrary (Org) Properties as JSON-String into LDAP. if (this._orgObj.getProperties() != null && !this._orgObj.getProperties().isEmpty()) { vOrgAttributes.put(new BasicAttribute(Constants.ldap_ddbOrg_Properties, serializer.serialize(this._orgObj.getProperties()))); } // finally bind the entry vCtx = LDAPConnector.getSingletonInstance().takeCtx(); ((InitialDirContext) vCtx).bind(vEntryDN.toString(), vCtx, vOrgAttributes); // -- Add default privilege(s) so we can assign performer // but only if that is not a copy in the export directory if (!this.isAddToLicensedOrgs()) { this._orgObj.getPrivilegesSet().add(PrivilegeEnum.ADMIN_ORG); // create org-privileges for (PrivilegeEnum p : this._orgObj.getPrivilegesSet()) { ThreadSinglePrivilegeCreate threadSinglePrivilegeCreate = new ThreadSinglePrivilegeCreate(p, this._orgObj, this._performer); threadSinglePrivilegeCreate.call(); } // -- Logging: LOG.log(Level.INFO, "One organization with DN: ''{0}'' was created.", new Object[] { vEntryDN }); } else { // -- Logging: LOG.log(Level.INFO, "One organization with DN: ''{0}'' was copied to the export directory.", new Object[] { vEntryDN }); } } catch (AssertionError ex) { LOG.log(Level.SEVERE, null, ex); throw new IllegalArgumentException(ex.getMessage(), ex.getCause()); } catch (IllegalAccessException ex) { LOG.log(Level.SEVERE, null, ex); throw new ExecutionException(ex.getMessage(), ex.getCause()); } catch (NamingException ex) { // LDAP: error code 68 - ENTRY_ALREADY_EXISTS: failed for Add // Request try { if (vCtx != null) { vCtx.close(); vCtx = null; } } catch (NamingException ex1) { LOG.log(Level.SEVERE, null, ex1); } try { vCtx = LDAPConnector.getSingletonInstance().getDirContext(); } catch (NamingException ex1) { LOG.log(Level.SEVERE, null, ex1); } catch (IllegalAccessException ex1) { LOG.log(Level.SEVERE, null, ex1); } throw new IllegalArgumentException(ex.getMessage()); } finally { if (vCtx != null) { try { LDAPConnector.getSingletonInstance().putCtx(vCtx); } catch (Exception ex) { LOG.log(Level.SEVERE, "Exception", ex); } } } } public AasPrincipal getPerformer() { return _performer; } public String getResourceId() { return null; } // *************************************************************************** /** * @return the _copyingOfOrgs */ public boolean isAddToLicensedOrgs() { return (_addToLicensedOrgs != null ? _addToLicensedOrgs.booleanValue() : false); } /** * @param pAddToLicensedOrgs the _addToLicensedOrgs to set */ public void setAddToLicensedOrgs(boolean pAddToLicensedOrgs) { this._addToLicensedOrgs = pAddToLicensedOrgs; } // *************************************************************************** /** * @return the _ingestingOperation */ public boolean isIngestingOperation() { return (_ingestingOperation != null ? _ingestingOperation.booleanValue() : false); } /** * @param pIngestingOperation the _ingestingOperation to set */ public void setIngestingOperation(boolean pIngestingOperation) { this._ingestingOperation = pIngestingOperation; } }