001 /*
002 Licensed to the Apache Software Foundation (ASF) under one
003 or more contributor license agreements. See the NOTICE file
004 distributed with this work for additional information
005 regarding copyright ownership. The ASF licenses this file
006 to you under the Apache License, Version 2.0 (the
007 "License"); you may not use this file except in compliance
008 with the License. You may obtain a copy of the License at
009
010 http://www.apache.org/licenses/LICENSE-2.0
011
012 Unless required by applicable law or agreed to in writing,
013 software distributed under the License is distributed on an
014 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 KIND, either express or implied. See the License for the
016 specific language governing permissions and limitations
017 under the License.
018 */
019 package org.apache.wiki;
020
021 import java.util.Date;
022 import java.util.Enumeration;
023 import java.util.HashMap;
024 import java.util.Map;
025
026 import org.apache.wiki.auth.acl.Acl;
027 import org.apache.wiki.auth.acl.AclEntry;
028 import org.apache.wiki.auth.acl.AclImpl;
029 import org.apache.wiki.providers.WikiPageProvider;
030
031 /**
032 * Simple wrapper class for the Wiki page attributes. The Wiki page
033 * content is moved around in Strings, though.
034 */
035
036 // FIXME: We need to rethink how metadata is being used - probably the
037 // author, date, etc. should also be part of the metadata. We also
038 // need to figure out the metadata lifecycle.
039
040 public class WikiPage
041 implements Cloneable,
042 Comparable
043 {
044 private static final long serialVersionUID = 1L;
045
046 private String m_name;
047 private WikiEngine m_engine;
048 private String m_wiki;
049 private Date m_lastModified;
050 private long m_fileSize = -1;
051 private int m_version = WikiPageProvider.LATEST_VERSION;
052 private String m_author = null;
053 private final HashMap<String,Object> m_attributes = new HashMap<String,Object>();
054
055 /**
056 * "Summary" is a short summary of the page. It is a String.
057 */
058 public static final String DESCRIPTION = "summary";
059
060 /** A special variable name for storing a page alias. */
061 public static final String ALIAS = "alias";
062
063 /** A special variable name for storing a redirect note */
064 public static final String REDIRECT = "redirect";
065
066 /** A special variable name for storing a changenote. */
067 public static final String CHANGENOTE = "changenote";
068
069 private Acl m_accessList = null;
070
071 /**
072 * Create a new WikiPage using a given engine and name.
073 *
074 * @param engine The WikiEngine that owns this page.
075 * @param name The name of the page.
076 */
077 public WikiPage( WikiEngine engine, String name )
078 {
079 m_engine = engine;
080 m_name = name;
081 m_wiki = engine.getApplicationName();
082 }
083
084 /**
085 * Returns the name of the page.
086 *
087 * @return The page name.
088 */
089 public String getName()
090 {
091 return m_name;
092 }
093
094 /**
095 * A WikiPage may have a number of attributes, which might or might not be
096 * available. Typically attributes are things that do not need to be stored
097 * with the wiki page to the page repository, but are generated
098 * on-the-fly. A provider is not required to save them, but they
099 * can do that if they really want.
100 *
101 * @param key The key using which the attribute is fetched
102 * @return The attribute. If the attribute has not been set, returns null.
103 */
104 public Object getAttribute( String key )
105 {
106 return m_attributes.get( key );
107 }
108
109 /**
110 * Sets an metadata attribute.
111 *
112 * @see #getAttribute(String)
113 * @param key The key for the attribute used to fetch the attribute later on.
114 * @param attribute The attribute value
115 */
116 public void setAttribute( String key, Object attribute )
117 {
118 m_attributes.put( key, attribute );
119 }
120
121 /**
122 * Returns the full attributes Map, in case external code needs
123 * to iterate through the attributes.
124 *
125 * @return The attribute Map. Please note that this is a direct
126 * reference, not a copy.
127 */
128 public Map getAttributes()
129 {
130 return m_attributes;
131 }
132
133 /**
134 * Removes an attribute from the page, if it exists.
135 *
136 * @param key The key for the attribute
137 * @return If the attribute existed, returns the object.
138 * @since 2.1.111
139 */
140 public Object removeAttribute( String key )
141 {
142 return m_attributes.remove( key );
143 }
144
145 /**
146 * Returns the date when this page was last modified.
147 *
148 * @return The last modification date
149 */
150 public Date getLastModified()
151 {
152 return m_lastModified;
153 }
154
155 /**
156 * Sets the last modification date. In general, this is only
157 * changed by the provider.
158 *
159 * @param date The date
160 */
161 public void setLastModified( Date date )
162 {
163 m_lastModified = date;
164 }
165
166 /**
167 * Sets the page version. In general, this is only changed
168 * by the provider.
169 *
170 * @param version The version number
171 */
172 public void setVersion( int version )
173 {
174 m_version = version;
175 }
176
177 /**
178 * Returns the version that this WikiPage instance represents.
179 *
180 * @return the version number of this page.
181 */
182 public int getVersion()
183 {
184 return m_version;
185 }
186
187 /**
188 * Returns the size of the page.
189 *
190 * @return the size of the page.
191 * @since 2.1.109
192 */
193 public long getSize()
194 {
195 return m_fileSize;
196 }
197
198 /**
199 * Sets the size. Typically called by the provider only.
200 *
201 * @param size The size of the page.
202 * @since 2.1.109
203 */
204 public void setSize( long size )
205 {
206 m_fileSize = size;
207 }
208
209 /**
210 * Returns the Acl for this page. May return <code>null</code>,
211 * in case there is no Acl defined, or it has not
212 * yet been set by {@link #setAcl(Acl)}.
213 *
214 * @return The access control list. May return null, if there is
215 * no acl.
216 */
217 public Acl getAcl()
218 {
219 return m_accessList;
220 }
221
222 /**
223 * Sets the Acl for this page. Note that method does <em>not</em>
224 * persist the Acl itself to back-end storage or in page markup;
225 * it merely sets the internal field that stores the Acl. To
226 * persist the Acl, callers should invoke
227 * {@link org.apache.wiki.auth.acl.AclManager#setPermissions(WikiPage, Acl)}.
228 * @param acl The Acl to set
229 */
230 public void setAcl( Acl acl )
231 {
232 m_accessList = acl;
233 }
234
235 /**
236 * Sets the author of the page. Typically called only by the provider.
237 *
238 * @param author The author name.
239 */
240 public void setAuthor( String author )
241 {
242 m_author = author;
243 }
244
245 /**
246 * Returns author name, or null, if no author has been defined.
247 *
248 * @return Author name, or possibly null.
249 */
250 public String getAuthor()
251 {
252 return m_author;
253 }
254
255 /**
256 * Returns the wiki nanme for this page
257 *
258 * @return The name of the wiki.
259 */
260 public String getWiki()
261 {
262 return m_wiki;
263 }
264
265 /**
266 * This method will remove all metadata from the page.
267 */
268 public void invalidateMetadata()
269 {
270 m_hasMetadata = false;
271 setAcl( null );
272 m_attributes.clear();
273 }
274
275 private boolean m_hasMetadata = false;
276
277 /**
278 * Returns <code>true</code> if the page has valid metadata; that is, it has been parsed.
279 * Note that this method is a kludge to support our pre-3.0 metadata system, and as such
280 * will go away with the new API.
281 *
282 * @return true, if the page has metadata.
283 */
284 public boolean hasMetadata()
285 {
286 return m_hasMetadata;
287 }
288
289 /**
290 * Sets the metadata flag to true. Never call.
291 */
292 public void setHasMetadata()
293 {
294 m_hasMetadata = true;
295 }
296
297 /**
298 * Returns a debug-suitable version of the page.
299 *
300 * @return A debug string.
301 */
302 public String toString()
303 {
304 return "WikiPage ["+m_wiki+":"+m_name+",ver="+m_version+",mod="+m_lastModified+"]";
305 }
306
307 /**
308 * Creates a deep clone of a WikiPage. Strings are not cloned, since
309 * they're immutable. Attributes are not cloned, only the internal
310 * HashMap (so if you modify the contents of a value of an attribute,
311 * these will reflect back to everyone).
312 *
313 * @return A deep clone of the WikiPage
314 */
315 public Object clone()
316 {
317 WikiPage p = new WikiPage( m_engine, m_name );
318
319 p.m_wiki = m_wiki;
320
321 p.m_author = m_author;
322 p.m_version = m_version;
323 p.m_lastModified = m_lastModified != null ? (Date)m_lastModified.clone() : null;
324
325 p.m_fileSize = m_fileSize;
326
327 for( Map.Entry<String,Object> entry : m_attributes.entrySet() )
328 {
329 p.m_attributes.put( entry.getKey(),
330 entry.getValue() );
331 }
332
333 if( m_accessList != null )
334 {
335 p.m_accessList = new AclImpl();
336
337 for( Enumeration< AclEntry > entries = m_accessList.entries(); entries.hasMoreElements(); )
338 {
339 AclEntry e = entries.nextElement();
340
341 p.m_accessList.addEntry( e );
342 }
343 }
344
345 return p;
346 }
347
348 /**
349 * Compares a page with another using the defined PageNameComparator. See org.apache.wiki.util.PageSorter.
350 *
351 * @param page The object to compare against
352 * @return -1, 0 or 1
353 */
354 public int compareTo( Object page )
355 {
356 return m_engine.getPageSorter().compare( this, (WikiPage) page );
357 }
358
359 /**
360 * A page is equal to another page if its name and version are equal.
361 *
362 * {@inheritDoc}
363 */
364 // TODO: I have a suspicion that defining this method causes some problems
365 // with page attributes and caching. So as of 2.7.32, it's disabled.
366 /*
367 public boolean equals( Object o )
368 {
369 if( o != null && o instanceof WikiPage )
370 {
371 WikiPage oo = (WikiPage) o;
372
373 if( oo.getName().equals( getName() ) )
374 {
375 if( oo.getVersion() == getVersion() )
376 {
377 return true;
378 }
379 }
380 }
381
382 return false;
383 }
384 */
385 /**
386 * {@inheritDoc}
387 */
388 public int hashCode()
389 {
390 return m_name.hashCode() * m_version;
391 }
392 }