001 /*
002 * Copyright 2011-2012 UnboundID Corp.
003 *
004 * This program is free software; you can redistribute it and/or modify
005 * it under the terms of the GNU General Public License (GPLv2 only)
006 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
007 * as published by the Free Software Foundation.
008 *
009 * This program is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012 * GNU General Public License for more details.
013 *
014 * You should have received a copy of the GNU General Public License
015 * along with this program; if not, see <http://www.gnu.org/licenses>.
016 */
017
018 package com.unboundid.scim.sdk;
019
020 import com.unboundid.scim.data.BaseResource;
021 import com.unboundid.scim.data.Meta;
022 import com.unboundid.scim.schema.ResourceDescriptor;
023
024 import javax.ws.rs.core.UriBuilder;
025 import java.net.URI;
026 import java.util.ArrayList;
027 import java.util.Collection;
028 import java.util.List;
029
030 /**
031 * This class provides an implementation of the SCIM server backend API that
032 * serves up the resource schema from a collection of ResourceDescriptors.
033 */
034 public class ResourceSchemaBackend extends SCIMBackend
035 {
036 private final Collection<ResourceDescriptor> resourceDescriptors;
037
038 /**
039 * Create a new ResourceSchemaBackend that serves up the schema provided
040 * from the ResourceDescriptors.
041 *
042 * @param resourceDescriptors The ResourceDescriptors to serve.
043 */
044 public ResourceSchemaBackend(
045 final Collection<ResourceDescriptor> resourceDescriptors) {
046 this.resourceDescriptors = resourceDescriptors;
047 }
048
049 /**
050 * {@inheritDoc}
051 */
052 @Override
053 public boolean authenticate(final String userID, final String password) {
054 return false;
055 }
056
057 /**
058 * {@inheritDoc}
059 */
060 @Override
061 public void finalizeBackend() {
062 resourceDescriptors.clear();
063 }
064
065 /**
066 * {@inheritDoc}
067 */
068 @Override
069 public ResourceDescriptor getResource(final GetResourceRequest request)
070 throws SCIMException {
071 ResourceDescriptor resourceDescriptor = null;
072 for(ResourceDescriptor rd : resourceDescriptors)
073 {
074 String id = rd.getSchema() +
075 SCIMConstants.SEPARATOR_CHAR_QUALIFIED_ATTRIBUTE + rd.getName();
076 if(id.equalsIgnoreCase(request.getResourceID()))
077 {
078 resourceDescriptor = rd;
079 break;
080 }
081 }
082
083 // Try to find a match in case the schema name was not provided.
084 if (resourceDescriptor == null)
085 {
086 for(ResourceDescriptor rd : resourceDescriptors)
087 {
088 if(rd.getName().equalsIgnoreCase(request.getResourceID()))
089 {
090 resourceDescriptor = rd;
091 break;
092 }
093 }
094 }
095
096 if(resourceDescriptor == null)
097 {
098 throw new ResourceNotFoundException("No Resource Schema with ID " +
099 request.getResourceID() + " exists");
100 }
101
102 return copyAndSetIdAndMetaAttributes(resourceDescriptor, request);
103 }
104
105 /**
106 * {@inheritDoc}
107 */
108 @Override
109 public Resources getResources(final GetResourcesRequest request)
110 throws SCIMException {
111 List<BaseResource> rds =
112 new ArrayList<BaseResource>(this.resourceDescriptors.size());
113
114 for(ResourceDescriptor resourceDescriptor : this.resourceDescriptors)
115 {
116 ResourceDescriptor copy =
117 copyAndSetIdAndMetaAttributes(resourceDescriptor, request);
118 if(request.getFilter() == null ||
119 copy.getScimObject().matchesFilter(request.getFilter()))
120 {
121 rds.add(copy);
122 }
123 }
124
125 int fromIndex = 0;
126 int total = rds.size();
127 if(request.getPageParameters() != null)
128 {
129 fromIndex = (int)request.getPageParameters().getStartIndex() - 1;
130 int endIndex =
131 Math.min(request.getPageParameters().getCount() + fromIndex,
132 rds.size());
133 rds = rds.subList(fromIndex, endIndex);
134 }
135
136 return new Resources<BaseResource>(rds, total, fromIndex + 1);
137 }
138
139 /**
140 * {@inheritDoc}
141 */
142 @Override
143 public BaseResource postResource(final PostResourceRequest request)
144 throws SCIMException {
145 throw new UnsupportedOperationException("POST operations are not allowed " +
146 "on the Resource Schema");
147 }
148
149 /**
150 * {@inheritDoc}
151 */
152 @Override
153 public void deleteResource(final DeleteResourceRequest request)
154 throws SCIMException {
155 throw new UnsupportedOperationException("DELETE operations are not " +
156 "allowed on the Resource Schema");
157 }
158
159 /**
160 * {@inheritDoc}
161 */
162 @Override
163 public BaseResource putResource(final PutResourceRequest request)
164 throws SCIMException {
165 throw new UnsupportedOperationException("PUT operations are not allowed " +
166 "on the Resource Schema");
167 }
168
169
170 /**
171 * Make a copy of the ResourceDescriptor and set the id and meta attributes
172 * from the provided information.
173 *
174 * @param resource The SCIM object whose id and meta attributes are to be
175 * set.
176 * @param request The SCIM request.
177 * @return The copy of the ResourceDescriptor.
178 */
179 public static ResourceDescriptor copyAndSetIdAndMetaAttributes(
180 final ResourceDescriptor resource,
181 final ResourceReturningRequest request)
182 {
183 ResourceDescriptor copy =
184 ResourceDescriptor.RESOURCE_DESCRIPTOR_FACTORY.createResource(
185 resource.getResourceDescriptor(),
186 new SCIMObject(resource.getScimObject()));
187
188 String id = resource.getSchema() +
189 SCIMConstants.SEPARATOR_CHAR_QUALIFIED_ATTRIBUTE + resource.getName();
190 copy.setId(id);
191
192 URI location = UriBuilder.fromUri(request.getBaseURL()).path(
193 resource.getResourceDescriptor().getEndpoint()).path(id).build();
194 copy.setMeta(new Meta(null, null,location, null));
195
196 // Pare down the attributes to those requested.
197 return ResourceDescriptor.RESOURCE_DESCRIPTOR_FACTORY.createResource(
198 resource.getResourceDescriptor(),
199 request.getAttributes().pareObject(copy.getScimObject()));
200 }
201 }