Home » Blog » Torweg: Pulse – The Web Application Framework

Torweg: Pulse – The Web Application Framework

About Torweg

Looking for a flexible shopping solution? pulse is so much more than just a CMS. It’s all for you.

Pulse is a framework that makes it simple to create websites and web applications. It is built on top of the Servlet API and uses Java technology, which means it can run on any platform where Java is supported. The first version of Pulse was created in May 2005 and has been updated regularly since then.

One of the key features of Pulse is its ease of use. Not only does it provide a simple way to build your own applications, but it also comes with a number of pre-built applications such as a content management system (CMS), an online store (Shop), and survey tools. These are all ready to use right away, so you don’t have to start from scratch when building your website.

Pulse also includes advanced features like a WebDAV based virtual file system for managing digital assets, mature user and role management, and flexible templating with XSLT 2.0/XPath

A few facts on pulse

The history of pulse

The whole story from the early plannings to where we are now.

Our Vision and Mission

We want to deliver the best solution for creating medium to large scale websites and browser based applications.

It’s all for you.

Copyright

pulse is licensed under the GPL v3. However pulse is build on top of other open source projects with various licenses. The icons used by pulse are non-free, please take note of their special license.

Legal Notice

What has to be said: who is responsible for the site, acknowledgements and how to reach us.

StringUtils.java

/*
2     * Copyright 2007 :torweg free software group
3     * 
4     * This program is free software: you can redistribute it and/or modify
5     * it under the terms of the GNU General Public License as published by
6     * the Free Software Foundation, either version 3 of the License, or
7     * (at your option) any later version.
8     * 
9     * This program is distributed in the hope that it will be useful,
10    * but WITHOUT ANY WARRANTY; without even the implied warranty of
11    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    * GNU General Public License for more details.
13    * 
14    * You should have received a copy of the GNU General Public License
15    * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16    *
17    */
18   package org.torweg.pulse.util;
19   
20   import java.io.PrintWriter;
21   import java.math.BigInteger;
22   import java.security.MessageDigest;
23   import java.security.NoSuchAlgorithmException;
24   import java.util.ArrayList;
25   import java.util.Arrays;
26   import java.util.Collections;
27   import java.util.Iterator;
28   import java.util.List;
29   import java.util.ListIterator;
30   
31   import org.torweg.pulse.invocation.lifecycle.Lifecycle;
32   import org.torweg.pulse.util.io.FastStringWriter;
33   
34   /**
35    * contains static utitity methods which are useful, when working with
36    * {@code String}s.
37    * 
38    * @author Thomas Weber
39    * @version $Revision: 2022 $
40    */
41   public final class StringUtils {
42   
43       /**
44        * the hexadecimal numbers.
45        */
46       private static final char[] HEX_NUMBERS = "0123456789ABCDEF".toCharArray();
47   
48       /**
49        * the base 60 numbers.
50        */
51       private static final char[] BASE_62_NUMBERS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
52               .toCharArray();
53   
54       /**
55        * 62.
56        */
57       private static final BigInteger SIXTY_TWO = BigInteger.valueOf(62L);
58   
59       /**
60        * hidden default constructor.
61        */
62       private StringUtils() {
63           super();
64       }
65   
66       /**
67        * returns the encoding of the given {@code String}.
68        * 
69        * @param s
70        *            the string to inspect
71        * @return the encoding
72        */
73       public static String getEncoding(final String s) {
74           return new java.io.InputStreamReader(new java.io.ByteArrayInputStream(
75                   s.getBytes())).getEncoding();
76       }
77   
78       /**
79        * turns a given {@code byte[]} into a string of hexadecimal numbers.
80        * <p>
81        * For example {@code 127, 126} get {@code FFFE}.
82        * </p>
83        * 
84        * @param bs
85        *            the bytes
86        * @return the hexadecimal string
87        */
88       public static String toHexString(final byte[] bs) {
89           StringBuilder hexString = new StringBuilder();
90           for (byte b : bs) {
91               int num = b + 128;
92               hexString.append(HEX_NUMBERS[num / 16]);
93               hexString.append(HEX_NUMBERS[num % 16]);
94           }
95           return hexString.toString();
96       }
97   
98       /**
99        * returns a base 62 string for the given {@code BigInteger}.
100       * 
101       * @param token
102       *            the number to be converted
103       * @return the base 62 representation
104       */
105      public static String toBase62String(final BigInteger token) {
106          BigInteger temp = token;
107          StringBuilder base62String = new StringBuilder();
108          if ((token.signum() < 0)) {
109              base62String.append('-');
110          }
111          while (temp.abs().compareTo(SIXTY_TWO) > 0) {
112              base62String
113                      .append(BASE_62_NUMBERS[temp.mod(SIXTY_TWO).intValue()]);
114              temp = temp.divide(SIXTY_TWO);
115          }
116          base62String.append(BASE_62_NUMBERS[temp.mod(SIXTY_TWO).intValue()]);
117          return base62String.toString();
118      }
119  
120      /**
121       * returns a base 62 string for the given byte array.
122       * 
123       * @param bytes
124       *            the byte array
125       * @return the base 62 string
126       */
127      public static String toBase62String(final byte[] bytes) {
128          return toBase62String(new BigInteger(bytes));
129      }
130  
131      /**
132       * returns the {@code BigInteger} represented by the given base 62 string.
133       * 
134       * @param base62
135       *            the base 62 encoded value
136       * @return the {@code BigInteger} represented by the given base 62 string
137       */
138      public static BigInteger fromBase62String(final String base62) {
139          BigInteger result = BigInteger.ZERO;
140          BigInteger base = BigInteger.ONE;
141          for (int i = 0; i < base62.length(); i++) {
142              char c = base62.charAt(i);
143              boolean found = false;
144              for (int k = 0; k < 62; k++) {
145                  if (BASE_62_NUMBERS[k] == c) {
146                      result = result.add(base.multiply(BigInteger.valueOf(k)));
147                      found = true;
148                      break;
149                  }
150              }
151              if (!found) {
152                  throw new NumberFormatException("Not a valid base 62 cypher: "
153                          + c);
154              }
155              base = base.multiply(SIXTY_TWO);
156          }
157          return result;
158      }
159  
160      /**
161       * hashes the given string using {@code <em>SHA-512</em>}.
162       * 
163       * @param str
164       *            the string
165       * @return the hash value as an hexadecimal string
166       * @throws NoSuchAlgorithmException
167       *             if the hashing algorithm is not available
168       */
169      public static String digest16(final String str)
170              throws NoSuchAlgorithmException {
171          return digest16(str.getBytes());
172      }
173  
174      /**
175       * hashes the byte[] using {@code <em>SHA-512</em>}.
176       * 
177       * @param bytes
178       *            the bytes
179       * @return the hash value as an hexadecimal string
180       * @throws NoSuchAlgorithmException
181       *             if the hashing algorithm is not available
182       */
183      public static String digest16(final byte[] bytes)
184              throws NoSuchAlgorithmException {
185          return toHexString(MessageDigest.getInstance("SHA-512").digest(
186                  Lifecycle.getSaltedHash(bytes)));
187      }
188  
189      /**
190       * hashes the string using {@code <em>SHA-512</em>}.
191       * 
192       * @param str
193       *            the string
194       * @return the hash value as a base 62 string
195       * @throws NoSuchAlgorithmException
196       *             if the hashing algorithm is not available
197       */
198      public static String digest62(final String str)
199              throws NoSuchAlgorithmException {
200          return digest62(str.getBytes());
201      }
202  
203      /**
204       * hashes the byte[] using {@code <em>SHA-512</em>}.
205       * 
206       * @param bytes
207       *            the bytes
208       * @return the hash value as a base 62 string
209       * @throws NoSuchAlgorithmException
210       *             if the hashing algorithm is not available
211       */
212      public static String digest62(final byte[] bytes)
213              throws NoSuchAlgorithmException {
214          return toBase62String(new BigInteger(MessageDigest.getInstance(
215                  "SHA-512").digest(Lifecycle.getSaltedHash(bytes))));
216      }
217  
218      /**
219       * returns the stack trace of the given {@code Throwable} as a string.
220       * 
221       * @param t
222       *            the throwable
223       * @return the stack trace of the given {@code Throwable} as a string
224       */
225      public static String getStackTrace(final Throwable t) {
226          FastStringWriter out = new FastStringWriter();
227          t.printStackTrace(new PrintWriter(out));
228          return out.toString();
229      }
230  
231      /**
232       * Inserts a fraction-dot into the given string at after the given position
233       * (counting from the back) filling the string up with 0s (zeros) if too
234       * short.
235       * 
236       * @param s
237       *            the string to format
238       * @param pos
239       *            the position to insert the fraction-dot
240       * 
241       * @return the formatted string
242       */
243      public static String insertFractionDot(final String s, final int pos) {
244          return StringUtils.insertFromBack(s, pos, ".", "0").toString();
245      }
246  
247      /**
248       * Inserts the given string <tt>insert</tt> at the specified position
249       * <tt>pos</tt> from the back of the string.
250       * 
251       * @param s
252       *            the string to be formatted
253       * @param pos
254       *            the position
255       * @param insert
256       *            the string to insert
257       * @param fill
258       *            the fill
259       * @return a {@code StringBuilder}
260       */
261      public static StringBuilder insertFromBack(final String s, final int pos,
262              final String insert, final String fill) {
263          StringBuilder builder = new StringBuilder(s);
264          while (builder.length() <= pos) {
265              builder.insert(0, fill);
266          }
267          // if (builder.length() < pos) {
268          // return builder;
269          // }
270          return builder.reverse().insert(pos, insert).reverse();
271      }
272  
273      /**
274       * ensures that the given {@code String} does not exceed the given maximum
275       * length, cutting off all characters exceeding characters.
276       * <p>
277       * {@code null} values will be converted to empty strings.
278       * </p>
279       * 
280       * @param s
281       *            the string
282       * @param l
283       *            the maximum length
284       * @return a string that is guaranteed to be less than or equal in length to
285       *         the given maximum length
286       */
287      public static String maxLength(final String s, final int l) {
288          if (s == null) {
289              return "";
290          }
291          if (s.length() <= l) {
292              return s;
293          }
294          return s.substring(0, l);
295      }
296  
297      /**
298       * returns either the given object's string representation or "null", if the
299       * given object is {@code null}.
300       * 
301       * @param o
302       *            the object
303       * @return either the given object's string representation or "null", if the
304       *         given object is {@code null}
305       */
306      public static String getString(final Object o) {
307          if (o == null) {
308              return "null";
309          }
310          return o.toString();
311      }
312  
313      /**
314       * Simple {@code ListIterator&lt;String&gt;} that operates on a
315       * {@code String} split by a regex.
316       * 
317       * @author Daniel Dietz
318       * @version $Revision: 2022 $
319       * 
320       */
321      public static class StringElementIterator implements ListIterator<String>,
322              Iterable<String> {
323  
324          /**
325           * The split-array the {@code StringElementIterator} operates on.
326           */
327          private final List<String> split;
328  
329          /**
330           * The index.
331           */
332          private int index = -1;
333  
334          /**
335           * Creates a new {@code StringElementIterator} for the given
336           * {@code String} and regex.
337           * 
338           * @param string
339           *            the {@code String}
340           * @param regex
341           *            the regex for the split
342           */
343          public StringElementIterator(final String string, final String regex) {
344              super();
345              this.split = Arrays.asList(string.split(regex));
346          }
347  
348          /**
349           * Creates a new reversed {@code StringElementIterator} for the given
350           * {@code String} and regex.
351           * 
352           * @param string
353           *            the {@code String}
354           * @param regex
355           *            the regex for the split
356           * @param reverse
357           *            flag, indicating whether the iterator shall process the
358           *            split {@code String} in reverse order ( {@code true})
359           */
360          public StringElementIterator(final String string, final String regex,
361                  final boolean reverse) {
362              super();
363              this.split = Arrays.asList(string.split(regex));
364              if (reverse) {
365                  Collections.reverse(this.split);
366              }
367          }
368  
369          /**
370           * Creates a new {@code StringElementIterator} which iterates over the
371           * given string array.
372           * 
373           * @param stringArray
374           *            the {@code String[]}
375           */
376          public StringElementIterator(final String[] stringArray) {
377              super();
378              this.split = Arrays.asList(stringArray);
379          }
380  
381          /**
382           * Private copy constructor for {@link #iterator()}.
383           * 
384           * @param s
385           *            the list of string elements
386           */
387          private StringElementIterator(final List<String> s) {
388              super();
389              this.split = s;
390          }
391  
392          /**
393           * Not implemented.
394           * 
395           * @param o
396           *            unused
397           * 
398           * @throws UnsupportedOperationException
399           *             always
400           * 
401           * @see java.util.ListIterator#add(java.lang.Object)
402           */
403          public final void add(final String o)
404                  throws UnsupportedOperationException {
405              throw new UnsupportedOperationException();
406          }
407  
408          /**
409           * Returns whether the {@code StringElementIterator} has more elements.
410           * 
411           * @return {@code true} if the {@code Iterator} has more elements,
412           *         {@code false} otherwise
413           * 
414           * @see java.util.ListIterator#hasNext()
415           */
416          public final boolean hasNext() {
417              return (this.index + 1 < this.split.size());
418          }
419  
420          /**
421           * Returns whether the {@code StringElementIterator} has an element
422           * prior to the current element.
423           * 
424           * @return {@code true} if the {@code Iterator} has previous elements,
425           *         {@code false} otherwise
426           * 
427           * @see java.util.ListIterator#hasPrevious()
428           */
429          public final boolean hasPrevious() {
430              return (this.index - 1 > -1);
431          }
432  
433          /**
434           * Returns the next element.
435           * 
436           * @return the next element
437           * 
438           * @see java.util.ListIterator#next()
439           */
440          public final String next() {
441              this.index++;
442              try {
443                  return this.split.get(this.index);
444              } catch (IndexOutOfBoundsException e) {
445                  this.index = this.split.size() - 1;
446                  throw e;
447              }
448          }
449  
450          /**
451           * Returns the next index.
452           * 
453           * @return the next index
454           * 
455           * @see java.util.ListIterator#nextIndex()
456           */
457          public final int nextIndex() {
458              return (this.index + 1);
459          }
460  
461          /**
462           * Returns the previous element.
463           * 
464           * @return the previous element
465           * 
466           * @see java.util.ListIterator#previous()
467           */
468          public final String previous() {
469              this.index--;
470              try {
471                  return this.split.get(this.index);
472              } catch (IndexOutOfBoundsException e) {
473                  this.index = -1;
474                  throw e;
475              }
476          }
477  
478          /**
479           * Returns the previous index.
480           * 
481           * @return the previous index
482           * 
483           * @see java.util.ListIterator#previousIndex()
484           */
485          public final int previousIndex() {
486              return (this.index - 1);
487          }
488  
489          /**
490           * Not implemented.
491           * 
492           * @throws UnsupportedOperationException
493           *             always
494           * 
495           * @see java.util.ListIterator#remove()
496           */
497          public final void remove() throws UnsupportedOperationException {
498              throw new UnsupportedOperationException(
499                      "remove() not supported for: " + this);
500          }
501  
502          /**
503           * Not implemented.
504           * 
505           * @param o
506           *            unused
507           * 
508           * @throws UnsupportedOperationException
509           *             always
510           * 
511           * @see java.util.ListIterator#set(java.lang.Object)
512           */
513          public final void set(final String o)
514                  throws UnsupportedOperationException {
515              throw new UnsupportedOperationException("set(" + o
516                      + ") not supported for: " + this);
517          }
518  
519          /**
520           * Returns a new {@code StringElementIterator} operating on a new
521           * instance of the internal list.
522           * 
523           * @return this {@code StringElementIterator}
524           * 
525           * @see java.lang.Iterable#iterator()
526           */
527          public final Iterator<String> iterator() {
528              return new StringElementIterator(new ArrayList<String>(this.split));
529          }
530  
531      }
532  
533  }

Leave a Comment