forked from Archives/Athou_commafeed
Compare commits
459 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
535f947f88 | ||
|
|
f27e243cc4 | ||
|
|
6a699ed5f1 | ||
|
|
9c1f5efab5 | ||
|
|
6b7ce56f6b | ||
|
|
b76ee4a2d0 | ||
|
|
b444a74a44 | ||
|
|
d43820cc82 | ||
|
|
e74e8fe1c2 | ||
|
|
9eb6e8ec27 | ||
|
|
fae94d3696 | ||
|
|
68e5ed64c9 | ||
|
|
f912d3b8bd | ||
|
|
fc03d2ee91 | ||
|
|
523b2b8db4 | ||
|
|
d547e9b6d7 | ||
|
|
71efc9f854 | ||
|
|
4f289f7467 | ||
|
|
02ef8bee71 | ||
|
|
ff5c1b00d7 | ||
|
|
30264be311 | ||
|
|
8ea44ab8c7 | ||
|
|
1b8ff7ca61 | ||
|
|
f00a066c22 | ||
|
|
859cf468aa | ||
|
|
5b486a917b | ||
|
|
9ace6b70f0 | ||
|
|
447029ae70 | ||
|
|
8ac52690fd | ||
|
|
6934b2bd27 | ||
|
|
6647e4fcd4 | ||
|
|
21710f55f3 | ||
|
|
27bd9a7489 | ||
|
|
630d37125c | ||
|
|
9424237534 | ||
|
|
cba3fbeb5f | ||
|
|
58778ccf43 | ||
|
|
6c61d47d78 | ||
|
|
35e02f9d98 | ||
|
|
58c1650863 | ||
|
|
9b14ffa14c | ||
|
|
96c09bf4cd | ||
|
|
737cec744a | ||
|
|
13ed92bb94 | ||
|
|
076594c78e | ||
|
|
b6b1b4ebbe | ||
|
|
4007f37492 | ||
|
|
532d671feb | ||
|
|
fed7a1ac84 | ||
|
|
ddfd170ea8 | ||
|
|
bae5c67dfa | ||
|
|
84f51603fb | ||
|
|
f73ddc03e9 | ||
|
|
a16d9877cc | ||
|
|
c24e9e083c | ||
|
|
101602c6f6 | ||
|
|
18a7bd1fd1 | ||
|
|
dfbd556bb8 | ||
|
|
040cdde8ba | ||
|
|
06373480ae | ||
|
|
5713a78f2e | ||
|
|
b9f2f17a24 | ||
|
|
9adc993472 | ||
|
|
dcd5f3d529 | ||
|
|
18e70a0e6b | ||
|
|
5ad57d1608 | ||
|
|
74eaf48ceb | ||
|
|
30bb0cb291 | ||
|
|
b50e6b93bd | ||
|
|
a0b5a1462d | ||
|
|
4910f93c94 | ||
|
|
4a52bd0cb7 | ||
|
|
b0bfb73952 | ||
|
|
69d049a69a | ||
|
|
7d75153362 | ||
|
|
748bfa31ae | ||
|
|
e7d995edbc | ||
|
|
a144fb2e48 | ||
|
|
7521013e11 | ||
|
|
c6321fc6b2 | ||
|
|
7d92d5d096 | ||
|
|
ab201d5016 | ||
|
|
efa38d5ee9 | ||
|
|
e8769d09a8 | ||
|
|
a216444825 | ||
|
|
fee3e10e6b | ||
|
|
4d71a8f3c2 | ||
|
|
fc104b0b01 | ||
|
|
3dcb351b36 | ||
|
|
600d05d08f | ||
|
|
6b6ff70ad3 | ||
|
|
891f660738 | ||
|
|
6901b9b728 | ||
|
|
c7f211a7f8 | ||
|
|
c48ea1152c | ||
|
|
f5d0eb94b4 | ||
|
|
cebeef04a0 | ||
|
|
3e77a83ca6 | ||
|
|
c872b335e7 | ||
|
|
cc1e173552 | ||
|
|
35e0567705 | ||
|
|
fb2add305e | ||
|
|
74d4c18c4c | ||
|
|
da3ce07485 | ||
|
|
c7ab179a9e | ||
|
|
6fd11fcd56 | ||
|
|
3966cf165b | ||
|
|
0b2ada5d1c | ||
|
|
4278101bbe | ||
|
|
8b43af49fc | ||
|
|
6e29e8426b | ||
|
|
af11d3c771 | ||
|
|
e5c5af4d57 | ||
|
|
3dbdf5adf2 | ||
|
|
4d7a030b70 | ||
|
|
3351262dd7 | ||
|
|
5ec4377502 | ||
|
|
9c8402c3a5 | ||
|
|
928a45e48e | ||
|
|
1d088c5eae | ||
|
|
cdcf81ab7c | ||
|
|
9f196bafe9 | ||
|
|
5c9e1406a1 | ||
|
|
0b42e00b29 | ||
|
|
88b98a138f | ||
|
|
136c37885d | ||
|
|
812988b31a | ||
|
|
191680a01b | ||
|
|
467d1a754d | ||
|
|
d1973922cd | ||
|
|
3b7689975d | ||
|
|
3386a71c5e | ||
|
|
7bb65a5e76 | ||
|
|
f3a9c8e0e2 | ||
|
|
22861ca8d0 | ||
|
|
19118ea241 | ||
|
|
4a9dc7249f | ||
|
|
5dad9c2eb8 | ||
|
|
d6b35b00b9 | ||
|
|
fda8ab500b | ||
|
|
66df421de2 | ||
|
|
33c62f08ca | ||
|
|
b660602809 | ||
|
|
6dfce2ca30 | ||
|
|
655e20e99e | ||
|
|
f2b80bdc08 | ||
|
|
10af873fa5 | ||
|
|
d87a5b14f8 | ||
|
|
b87a18b993 | ||
|
|
c4185034e4 | ||
|
|
9d64426b00 | ||
|
|
c81cc8bea4 | ||
|
|
90e680d6be | ||
|
|
04c0833111 | ||
|
|
06151eab3b | ||
|
|
3dcb8590f6 | ||
|
|
a9b313aa4a | ||
|
|
1f2e35060b | ||
|
|
a96862fffa | ||
|
|
68cb8e194d | ||
|
|
c164926c54 | ||
|
|
de7516116d | ||
|
|
fccfe5b088 | ||
|
|
23aa5fa0a3 | ||
|
|
d384c0a141 | ||
|
|
18058c2a36 | ||
|
|
71727202f3 | ||
|
|
eee0b949de | ||
|
|
3cbbb67b0c | ||
|
|
7879f66e78 | ||
|
|
c14ac37495 | ||
|
|
73a77183aa | ||
|
|
09cfa21091 | ||
|
|
c193571ece | ||
|
|
04bc92b071 | ||
|
|
94e58a449c | ||
|
|
9d044195aa | ||
|
|
caff34cc3b | ||
|
|
34c5c0b1f7 | ||
|
|
906801e13c | ||
|
|
dad4c6b866 | ||
|
|
090462022f | ||
|
|
cbf9f65fb4 | ||
|
|
5a493cd55d | ||
|
|
dfc204ef05 | ||
|
|
56c6e2d29c | ||
|
|
db03dd12a0 | ||
|
|
6c67e6363a | ||
|
|
e2888beb4c | ||
|
|
bba9166885 | ||
|
|
504e4eab3e | ||
|
|
2e475c35cc | ||
|
|
ccf18758fb | ||
|
|
68f9852790 | ||
|
|
d0150de003 | ||
|
|
e2b792335b | ||
|
|
ece38c9e59 | ||
|
|
a19b5090bf | ||
|
|
e4b3c35892 | ||
|
|
4b229a759a | ||
|
|
1e9e42ac48 | ||
|
|
245a48f66e | ||
|
|
e6d8397550 | ||
|
|
d59bd43846 | ||
|
|
c1579c83c7 | ||
|
|
4d782e60ad | ||
|
|
c702f47927 | ||
|
|
9110cfd923 | ||
|
|
e40dd14bbf | ||
|
|
90aaae9959 | ||
|
|
e81dda0fa8 | ||
|
|
f93796d036 | ||
|
|
d06359cb81 | ||
|
|
8b68fb578f | ||
|
|
cca300e419 | ||
|
|
77c3ec0bbe | ||
|
|
ed81fc576a | ||
|
|
435fcb9669 | ||
|
|
9020d95b62 | ||
|
|
84d7a501d4 | ||
|
|
e65dd49d69 | ||
|
|
a705cbe6c2 | ||
|
|
60b8af3860 | ||
|
|
9ac4187aa8 | ||
|
|
6419d29489 | ||
|
|
4684e43f42 | ||
|
|
a477c9fa6d | ||
|
|
d1be331f99 | ||
|
|
cbc792d406 | ||
|
|
0313c5c560 | ||
|
|
18aa2fcd92 | ||
|
|
10461941d7 | ||
|
|
e6050219bc | ||
|
|
81481c37fe | ||
|
|
5ea92a7d18 | ||
|
|
f40630aced | ||
|
|
81850acdfe | ||
|
|
6819d5aa8b | ||
|
|
2aef4e5d05 | ||
|
|
6d4d2c3e7e | ||
|
|
87bcaa4731 | ||
|
|
5d2378f291 | ||
|
|
253507d14b | ||
|
|
548fb7099b | ||
|
|
0dd7c777ee | ||
|
|
6812bf2388 | ||
|
|
12bcbfa9f7 | ||
|
|
b5dfd371d9 | ||
|
|
e09d7fb103 | ||
|
|
0fe3afe254 | ||
|
|
db50d50c19 | ||
|
|
691bdb1512 | ||
|
|
d50b712bca | ||
|
|
3b68e4f32b | ||
|
|
259b9a90dd | ||
|
|
f4c5fd7eb4 | ||
|
|
3cd42d03f0 | ||
|
|
3497b82e8c | ||
|
|
15a24e4e75 | ||
|
|
96837f908e | ||
|
|
4ea5ebbf9e | ||
|
|
281e015376 | ||
|
|
5825a16aff | ||
|
|
2586a8c433 | ||
|
|
9f7c9c3428 | ||
|
|
9790ba735b | ||
|
|
e3dbcac9fb | ||
|
|
1c99929429 | ||
|
|
9b2cdbbb18 | ||
|
|
928cf1220e | ||
|
|
c0557856a3 | ||
|
|
97c2cc3d15 | ||
|
|
a94ef980bb | ||
|
|
eea0c24d2b | ||
|
|
c8fded3c56 | ||
|
|
8f2ba5e186 | ||
|
|
5ce2823d0b | ||
|
|
a0c70d326f | ||
|
|
5f28fd4114 | ||
|
|
7151db0909 | ||
|
|
e82888f8f3 | ||
|
|
4fb60a6ec6 | ||
|
|
27f22f6094 | ||
|
|
7497a0151a | ||
|
|
41f133afb1 | ||
|
|
4b15ecbc1b | ||
|
|
6498130850 | ||
|
|
24bd1121af | ||
|
|
3cccf741d6 | ||
|
|
0a2d2c3f43 | ||
|
|
969da0f2a6 | ||
|
|
2061b68a2f | ||
|
|
443dea5055 | ||
|
|
a4c6365ede | ||
|
|
c9c044386e | ||
|
|
2744f8285c | ||
|
|
7bf5f20b06 | ||
|
|
b43aa84c2a | ||
|
|
dd27d88309 | ||
|
|
8dc36a72b2 | ||
|
|
d3ca301675 | ||
|
|
43e3469e63 | ||
|
|
cdc3dc6740 | ||
|
|
6fba8b61e7 | ||
|
|
b34594a1dc | ||
|
|
19964d253e | ||
|
|
165f3ed25a | ||
|
|
5058290103 | ||
|
|
358a6029a1 | ||
|
|
fa4bfa729d | ||
|
|
9c9e43cf46 | ||
|
|
b7e5bd0144 | ||
|
|
58dc6f5832 | ||
|
|
f409af1c37 | ||
|
|
9e0c94f1a4 | ||
|
|
3794d61a77 | ||
|
|
d22da54d53 | ||
|
|
8e34c44e0d | ||
|
|
b71434acf6 | ||
|
|
7e158ed9b9 | ||
|
|
2ec0d067f3 | ||
|
|
effc65b777 | ||
|
|
c48e248283 | ||
|
|
f9e9a4547c | ||
|
|
63e35aba6d | ||
|
|
8f852fb9ac | ||
|
|
bf6a13b43f | ||
|
|
12030f6ce9 | ||
|
|
07da878bba | ||
|
|
8d5c3bdec8 | ||
|
|
ce95772afa | ||
|
|
b9f27b2b00 | ||
|
|
0059cabebe | ||
|
|
326ee79c8c | ||
|
|
54cc265ee6 | ||
|
|
e38778b4d0 | ||
|
|
6152d3c14a | ||
|
|
8a172170ea | ||
|
|
64b5d64709 | ||
|
|
67d7315003 | ||
|
|
47da4a2a1a | ||
|
|
174be9c2d1 | ||
|
|
9b68539322 | ||
|
|
2a4660ffa6 | ||
|
|
dce0cf7ee4 | ||
|
|
d6c39d4aba | ||
|
|
fd7e183f40 | ||
|
|
bf78a80f29 | ||
|
|
0ff630b8bd | ||
|
|
49b9e3f278 | ||
|
|
a4cc65c6a4 | ||
|
|
0b46187ac5 | ||
|
|
14ef5af936 | ||
|
|
539d9c6d0e | ||
|
|
56bcc5ef5e | ||
|
|
d6b0324e24 | ||
|
|
ff044e2592 | ||
|
|
3c7747ab97 | ||
|
|
34d97221ed | ||
|
|
84e78d34cd | ||
|
|
ac73806aee | ||
|
|
2105e9a5c9 | ||
|
|
2a36cc4327 | ||
|
|
c3feaf9a15 | ||
|
|
d8537a98aa | ||
|
|
42a6001ba5 | ||
|
|
4d9eb35230 | ||
|
|
e4ac296a1f | ||
|
|
01b49e7864 | ||
|
|
bd0b85a8d2 | ||
|
|
3d59a4c516 | ||
|
|
08ceff0f03 | ||
|
|
d6ae88ac43 | ||
|
|
5c8f016dd6 | ||
|
|
17288017d8 | ||
|
|
1e2757b52f | ||
|
|
0dce2f057e | ||
|
|
e017c5c304 | ||
|
|
a3e828f90a | ||
|
|
74e5c24fdc | ||
|
|
76c0abaa22 | ||
|
|
a52b5fd711 | ||
|
|
ffa51406b6 | ||
|
|
0b3b267e63 | ||
|
|
fcdb9d8257 | ||
|
|
04943ca525 | ||
|
|
574d4a1223 | ||
|
|
7349814cb2 | ||
|
|
114c5eb356 | ||
|
|
191f861f6e | ||
|
|
fac1fcc3a6 | ||
|
|
d0490c5eb5 | ||
|
|
2673efa9fc | ||
|
|
d4bce7b0a1 | ||
|
|
ba4a7ce6ab | ||
|
|
58f10153ab | ||
|
|
e7b65e3f26 | ||
|
|
fe91473748 | ||
|
|
0140402ad4 | ||
|
|
f56cba59ae | ||
|
|
fed74f05fc | ||
|
|
0888f11257 | ||
|
|
7205d5bb9c | ||
|
|
17a5ef882f | ||
|
|
ea68dbc56f | ||
|
|
0cec8af074 | ||
|
|
f7d0fc5768 | ||
|
|
bcaab694c8 | ||
|
|
247a3d5ab3 | ||
|
|
8e262a1e10 | ||
|
|
f63695bdc7 | ||
|
|
b051613b62 | ||
|
|
b886379d34 | ||
|
|
2a780dd2bb | ||
|
|
9cf7b80110 | ||
|
|
8fee73f1d1 | ||
|
|
36edb9373b | ||
|
|
374c4b265a | ||
|
|
db0b685ae1 | ||
|
|
23d33b8402 | ||
|
|
8a57be3e63 | ||
|
|
823cb03f9b | ||
|
|
e96cbcb057 | ||
|
|
fa0e7bcb54 | ||
|
|
20292a7742 | ||
|
|
943bde7eed | ||
|
|
9701af0736 | ||
|
|
1456cc40e1 | ||
|
|
dc1f88c44c | ||
|
|
55c916956f | ||
|
|
51eda57618 | ||
|
|
d6a55e1ec0 | ||
|
|
b78210421c | ||
|
|
1324269f1d | ||
|
|
cda6cb5cc0 | ||
|
|
c1b8619b26 | ||
|
|
4203e25321 | ||
|
|
aa02c7b93a | ||
|
|
0ff477579b | ||
|
|
62a8e8c119 | ||
|
|
fa212e0911 | ||
|
|
c8ad902a60 | ||
|
|
f05515d7d6 | ||
|
|
95bbcce941 | ||
|
|
d6b98f1518 | ||
|
|
bd9b1b11c5 | ||
|
|
e4c4960972 | ||
|
|
2a26031261 | ||
|
|
1d6e212955 | ||
|
|
9fa3743d21 | ||
|
|
7b373c79d9 | ||
|
|
4e9266e2d5 | ||
|
|
ea957e297c | ||
|
|
9320b6beb8 | ||
|
|
1319bf4a8c | ||
|
|
78b1ec6e6a | ||
|
|
6d4cbb889d | ||
|
|
27d16265d6 | ||
|
|
9888e23cd9 |
3
.openshift/README.md
Normal file
3
.openshift/README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
For information about .openshift directory, consult the documentation:
|
||||||
|
|
||||||
|
http://openshift.github.io/documentation/oo_user_guide.html#the-openshift-directory
|
||||||
3
.openshift/action_hooks/README.md
Normal file
3
.openshift/action_hooks/README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
For information about action hooks, consult the documentation:
|
||||||
|
|
||||||
|
http://openshift.github.io/documentation/oo_user_guide.html#action-hooks
|
||||||
36
.openshift/action_hooks/build
Executable file
36
.openshift/action_hooks/build
Executable file
@@ -0,0 +1,36 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
if [ ! -d $OPENSHIFT_DATA_DIR/jdk1.8.0_20 ]
|
||||||
|
then
|
||||||
|
cd $OPENSHIFT_DATA_DIR
|
||||||
|
wget http://www.java.net/download/jdk8u20/archive/b17/binaries/jdk-8u20-ea-bin-b17-linux-x64-04_jun_2014.tar.gz
|
||||||
|
tar xvf *.tar.gz
|
||||||
|
rm -f *.tar.gz
|
||||||
|
fi
|
||||||
|
if [ ! -d $OPENSHIFT_DATA_DIR/apache-maven-3.2.3 ]
|
||||||
|
then
|
||||||
|
cd $OPENSHIFT_DATA_DIR
|
||||||
|
wget http://archive.apache.org/dist/maven/maven-3/3.2.3/binaries/apache-maven-3.2.3-bin.tar.gz
|
||||||
|
tar xvf *.tar.gz
|
||||||
|
rm -f *.tar.gz
|
||||||
|
fi
|
||||||
|
export M2=$OPENSHIFT_DATA_DIR/apache-maven-3.2.3/bin
|
||||||
|
export JAVA_HOME=$OPENSHIFT_DATA_DIR/jdk1.8.0_20
|
||||||
|
export PATH=$JAVA_HOME/bin:$M2:$PATH
|
||||||
|
|
||||||
|
cd $OPENSHIFT_REPO_DIR
|
||||||
|
rm -rf $OPENSHIFT_REPO_DIR/node
|
||||||
|
rm -rf $OPENSHIFT_REPO_DIR/node_modules
|
||||||
|
rm -rf $OPENSHIFT_TMP_DIR/npm
|
||||||
|
rm -rf $OPENSHIFT_TMP_DIR/npmrc
|
||||||
|
rm -rf $OPENSHIFT_TMP_DIR/m2
|
||||||
|
rm -rf $OPENSHIFT_TMP_DIR/local
|
||||||
|
|
||||||
|
export NPM_CONFIG_PREFIX="$OPENSHIFT_TMP_DIR/npm"
|
||||||
|
export NPM_CONFIG_USERCONFIG="$OPENSHIFT_TMP_DIR/npmrc"
|
||||||
|
export NPM_CONFIG_CACHE="$OPENSHIFT_TMP_DIR/npm/cache"
|
||||||
|
export MAVEN_OPTS="-Dmaven.repo.local=$OPENSHIFT_TMP_DIR/m2"
|
||||||
|
export HOME="$OPENSHIFT_TMP_DIR/local"
|
||||||
|
|
||||||
|
export NPM_CONFIG_ARCH="x64"
|
||||||
|
|
||||||
|
mvn clean package -DskipTests -Dos.arch=x64 -s .openshift/settings.xml
|
||||||
9
.openshift/action_hooks/deploy
Executable file
9
.openshift/action_hooks/deploy
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
cd $OPENSHIFT_REPO_DIR
|
||||||
|
sed -i 's/@OPENSHIFT_DIY_IP@/'"$OPENSHIFT_DIY_IP"'/g' .openshift/config.mysql.yml
|
||||||
|
sed -i 's/@OPENSHIFT_DIY_PORT@/'"$OPENSHIFT_DIY_PORT"'/g' .openshift/config.mysql.yml
|
||||||
|
sed -i 's/@OPENSHIFT_APP_DNS@/'"$OPENSHIFT_APP_DNS"'/g' .openshift/config.mysql.yml
|
||||||
|
sed -i 's/@OPENSHIFT_APP_NAME@/'"$OPENSHIFT_APP_NAME"'/g' .openshift/config.mysql.yml
|
||||||
|
sed -i 's/@OPENSHIFT_MYSQL_DB_HOST@/'"$OPENSHIFT_MYSQL_DB_HOST"'/g' .openshift/config.mysql.yml
|
||||||
|
sed -i 's/@OPENSHIFT_MYSQL_DB_USERNAME@/'"$OPENSHIFT_MYSQL_DB_USERNAME"'/g' .openshift/config.mysql.yml
|
||||||
|
sed -i 's/@OPENSHIFT_MYSQL_DB_PASSWORD@/'"$OPENSHIFT_MYSQL_DB_PASSWORD"'/g' .openshift/config.mysql.yml
|
||||||
4
.openshift/action_hooks/start
Executable file
4
.openshift/action_hooks/start
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
cd $OPENSHIFT_REPO_DIR
|
||||||
|
export JAVA_HOME=$OPENSHIFT_DATA_DIR/jdk1.8.0_20
|
||||||
|
nohup $JAVA_HOME/bin/java -jar target/commafeed.jar server .openshift/config.mysql.yml > ${OPENSHIFT_DIY_LOG_DIR}/commafeed.log 2>&1 &
|
||||||
8
.openshift/action_hooks/stop
Executable file
8
.openshift/action_hooks/stop
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
source $OPENSHIFT_CARTRIDGE_SDK_BASH
|
||||||
|
if [ -z "$(ps -ef | grep commafeed.jar | grep -v grep)" ]
|
||||||
|
then
|
||||||
|
client_result "Application is already stopped"
|
||||||
|
else
|
||||||
|
kill `ps -ef | grep commafeed.jar | grep -v grep | awk '{ print $2 }'` > /dev/null 2>&1
|
||||||
|
fi
|
||||||
113
.openshift/config.mysql.yml
Normal file
113
.openshift/config.mysql.yml
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
# CommaFeed settings
|
||||||
|
# ------------------
|
||||||
|
app:
|
||||||
|
# url used to access commafeed
|
||||||
|
publicUrl: https://@OPENSHIFT_APP_DNS@/
|
||||||
|
|
||||||
|
# wether to allow user registrations
|
||||||
|
allowRegistrations: false
|
||||||
|
|
||||||
|
# create a demo account the first time the app starts
|
||||||
|
createDemoAccount: false
|
||||||
|
|
||||||
|
# put your google analytics tracking code here
|
||||||
|
googleAnalyticsTrackingCode:
|
||||||
|
|
||||||
|
# put your google server key (used for youtube favicon fetching)
|
||||||
|
googleAuthKey:
|
||||||
|
|
||||||
|
# number of http threads
|
||||||
|
backgroundThreads: 3
|
||||||
|
|
||||||
|
# number of database updating threads
|
||||||
|
databaseUpdateThreads: 1
|
||||||
|
|
||||||
|
# settings for sending emails (password recovery)
|
||||||
|
smtpHost:
|
||||||
|
smtpPort:
|
||||||
|
smtpTls: false
|
||||||
|
smtpUserName:
|
||||||
|
smtpPassword:
|
||||||
|
|
||||||
|
# wether this commafeed instance has a lot of feeds to refresh
|
||||||
|
# leave this to false in almost all cases
|
||||||
|
heavyLoad: false
|
||||||
|
|
||||||
|
# minimum amount of time commafeed will wait before refreshing the same feed
|
||||||
|
refreshIntervalMinutes: 15
|
||||||
|
|
||||||
|
# wether to enable pubsub
|
||||||
|
# probably not needed if refreshIntervalMinutes is low
|
||||||
|
pubsubhubbub: false
|
||||||
|
|
||||||
|
# if enabled, images in feed entries will be proxied through the server instead of accessed directly by the browser
|
||||||
|
# useful if commafeed is usually accessed through a restricting proxy
|
||||||
|
imageProxyEnabled: false
|
||||||
|
|
||||||
|
# database query timeout (in milliseconds), 0 to disable
|
||||||
|
queryTimeout: 0
|
||||||
|
|
||||||
|
# time to keep unread statuses (in days), 0 to disable
|
||||||
|
keepStatusDays: 0
|
||||||
|
|
||||||
|
# entries to keep per feed, old entries will be deleted, 0 to disable
|
||||||
|
maxFeedCapacity: 500
|
||||||
|
|
||||||
|
# cache service to use, possible values are 'noop' and 'redis'
|
||||||
|
cache: noop
|
||||||
|
|
||||||
|
# announcement string displayed on the main page
|
||||||
|
announcement:
|
||||||
|
|
||||||
|
# Database connection
|
||||||
|
# -------------------
|
||||||
|
# for MySQL
|
||||||
|
# driverClass is com.mysql.jdbc.Driver
|
||||||
|
# url is jdbc:mysql://localhost/commafeed?autoReconnect=true&failOverReadOnly=false&maxReconnects=20&rewriteBatchedStatements=true
|
||||||
|
#
|
||||||
|
# for PostgreSQL
|
||||||
|
# driverClass is org.postgresql.Driver
|
||||||
|
# url is jdbc:postgresql://localhost:5432/commafeed
|
||||||
|
#
|
||||||
|
# for Microsoft SQL Server
|
||||||
|
# driverClass is net.sourceforge.jtds.jdbc.Driver
|
||||||
|
# url is jdbc:jtds:sqlserver://localhost:1433/commafeed;instance=<instanceName, remove if not needed>
|
||||||
|
|
||||||
|
database:
|
||||||
|
driverClass: com.mysql.jdbc.Driver
|
||||||
|
url: jdbc:mysql://@OPENSHIFT_MYSQL_DB_HOST@/@OPENSHIFT_APP_NAME@?autoReconnect=true&failOverReadOnly=false&maxReconnects=20&rewriteBatchedStatements=true
|
||||||
|
user: @OPENSHIFT_MYSQL_DB_USERNAME@
|
||||||
|
password: @OPENSHIFT_MYSQL_DB_PASSWORD@
|
||||||
|
properties:
|
||||||
|
charSet: UTF-8
|
||||||
|
maxWaitForConnection: 1s
|
||||||
|
validationQuery: "/* CommaFeed Health Check */ SELECT 1"
|
||||||
|
minSize: 1
|
||||||
|
maxSize: 50
|
||||||
|
checkConnectionWhileIdle: true
|
||||||
|
maxConnectionAge: 30m
|
||||||
|
|
||||||
|
server:
|
||||||
|
applicationConnectors:
|
||||||
|
- type: http
|
||||||
|
port: @OPENSHIFT_DIY_PORT@
|
||||||
|
bindHost: @OPENSHIFT_DIY_IP@
|
||||||
|
adminConnectors:
|
||||||
|
- type: http
|
||||||
|
port: 15000
|
||||||
|
bindHost: @OPENSHIFT_DIY_IP@
|
||||||
|
logging:
|
||||||
|
level: WARN
|
||||||
|
loggers:
|
||||||
|
com.commafeed: INFO
|
||||||
|
liquibase: INFO
|
||||||
|
io.dropwizard.server.ServerFactory: INFO
|
||||||
|
appenders:
|
||||||
|
- type: console
|
||||||
|
- type: file
|
||||||
|
currentLogFilename: log/commafeed.log
|
||||||
|
threshold: ALL
|
||||||
|
archive: true
|
||||||
|
archivedLogFilenamePattern: log/commafeed-%d.log
|
||||||
|
archivedFileCount: 5
|
||||||
|
timeZone: UTC
|
||||||
0
.openshift/cron/daily/.gitignore
vendored
Normal file
0
.openshift/cron/daily/.gitignore
vendored
Normal file
0
.openshift/cron/hourly/.gitignore
vendored
Normal file
0
.openshift/cron/hourly/.gitignore
vendored
Normal file
0
.openshift/cron/minutely/.gitignore
vendored
Normal file
0
.openshift/cron/minutely/.gitignore
vendored
Normal file
0
.openshift/cron/monthly/.gitignore
vendored
Normal file
0
.openshift/cron/monthly/.gitignore
vendored
Normal file
16
.openshift/cron/weekly/README
Normal file
16
.openshift/cron/weekly/README
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
Run scripts or jobs on a weekly basis
|
||||||
|
=====================================
|
||||||
|
Any scripts or jobs added to this directory will be run on a scheduled basis
|
||||||
|
(weekly) using run-parts.
|
||||||
|
|
||||||
|
run-parts ignores any files that are hidden or dotfiles (.*) or backup
|
||||||
|
files (*~ or *,) or named *.{rpmsave,rpmorig,rpmnew,swp,cfsaved} and handles
|
||||||
|
the files named jobs.deny and jobs.allow specially.
|
||||||
|
|
||||||
|
In this specific example, the chronograph script is the only script or job file
|
||||||
|
executed on a weekly basis (due to white-listing it in jobs.allow). And the
|
||||||
|
README and chrono.dat file are ignored either as a result of being black-listed
|
||||||
|
in jobs.deny or because they are NOT white-listed in the jobs.allow file.
|
||||||
|
|
||||||
|
For more details, please see ../README.cron file.
|
||||||
|
|
||||||
1
.openshift/cron/weekly/chrono.dat
Normal file
1
.openshift/cron/weekly/chrono.dat
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Time And Relative D...n In Execution (Open)Shift!
|
||||||
3
.openshift/cron/weekly/chronograph
Executable file
3
.openshift/cron/weekly/chronograph
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo "`date`: `cat $(dirname \"$0\")/chrono.dat`"
|
||||||
12
.openshift/cron/weekly/jobs.allow
Normal file
12
.openshift/cron/weekly/jobs.allow
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#
|
||||||
|
# Script or job files listed in here (one entry per line) will be
|
||||||
|
# executed on a weekly-basis.
|
||||||
|
#
|
||||||
|
# Example: The chronograph script will be executed weekly but the README
|
||||||
|
# and chrono.dat files in this directory will be ignored.
|
||||||
|
#
|
||||||
|
# The README file is actually ignored due to the entry in the
|
||||||
|
# jobs.deny which is checked before jobs.allow (this file).
|
||||||
|
#
|
||||||
|
chronograph
|
||||||
|
|
||||||
7
.openshift/cron/weekly/jobs.deny
Normal file
7
.openshift/cron/weekly/jobs.deny
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
# Any script or job files listed in here (one entry per line) will NOT be
|
||||||
|
# executed (read as ignored by run-parts).
|
||||||
|
#
|
||||||
|
|
||||||
|
README
|
||||||
|
|
||||||
3
.openshift/markers/README.md
Normal file
3
.openshift/markers/README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
For information about markers, consult the documentation:
|
||||||
|
|
||||||
|
http://openshift.github.io/documentation/oo_user_guide.html#markers
|
||||||
0
.openshift/markers/java8
Normal file
0
.openshift/markers/java8
Normal file
41
.openshift/settings.xml
Normal file
41
.openshift/settings.xml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<settings>
|
||||||
|
<mirrors>
|
||||||
|
<mirror>
|
||||||
|
<id>nexus</id>
|
||||||
|
<mirrorOf>central</mirrorOf>
|
||||||
|
<url>http://mirror1.ops.rhcloud.com/nexus/content/groups/public</url>
|
||||||
|
</mirror>
|
||||||
|
</mirrors>
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>nexus</id>
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>central</id>
|
||||||
|
<url>http://central</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
<pluginRepositories>
|
||||||
|
<pluginRepository>
|
||||||
|
<id>central</id>
|
||||||
|
<url>http://central</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</pluginRepository>
|
||||||
|
</pluginRepositories>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
<activeProfiles>
|
||||||
|
<activeProfile>nexus</activeProfile>
|
||||||
|
</activeProfiles>
|
||||||
|
</settings>
|
||||||
3
.travis.yml
Normal file
3
.travis.yml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
language: java
|
||||||
|
jdk:
|
||||||
|
- oraclejdk8
|
||||||
45
CHANGELOG
Normal file
45
CHANGELOG
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
v 2.3.0
|
||||||
|
- dropwizard upgrade 0.9.1
|
||||||
|
- feed enclosures are hidden if they already displayed in the content
|
||||||
|
- fix youtube favicons
|
||||||
|
- various internationalization fixes
|
||||||
|
v 2.2.0
|
||||||
|
- fix youtube and instagram favicon fetching
|
||||||
|
- mark as read filter was lost when a feed was rearranged with drag&drop
|
||||||
|
- feed entry categories are now displayed if available
|
||||||
|
- various performance and dependencies upgrades
|
||||||
|
- java8 is now required
|
||||||
|
v 2.1.0
|
||||||
|
- dropwizard upgrade to 0.8.0
|
||||||
|
- you have to remove the "app.contextPath" setting from your yml file, you can optionally use server.applicationContextPath instead
|
||||||
|
- new setting app.maxFeedCapacity for deleting old entries
|
||||||
|
- ability to set filtering expressions for subscriptions to automatically mark new entries as read based on title, content, author or url.
|
||||||
|
- ability to use !keyword or -keyword to exclude a keyword from a search query
|
||||||
|
- facebook feeds now show user favicon instead of facebook favicon
|
||||||
|
- new dark theme 'nightsky'
|
||||||
|
v 2.0.3
|
||||||
|
- internet explorer ajax cache workaround
|
||||||
|
- categories are now deletable again
|
||||||
|
- openshift support is back
|
||||||
|
- youtube feeds now show user favicon instead of youtube favicon
|
||||||
|
v 2.0.2
|
||||||
|
- api using the api key is now working again
|
||||||
|
- context path is now configurable in config.yml (see app.contextPath in config.yml.example)
|
||||||
|
- fix login on firefox when fields are autofilled by the browser
|
||||||
|
- fix scrolling of subscriptions list on mobile
|
||||||
|
- user is now logged in after registration
|
||||||
|
- fix link to documentation on home page and about page
|
||||||
|
- fields autocomplete is disabled on the profile page
|
||||||
|
- users are able to delete their account again
|
||||||
|
- chinese and malaysian translation files are now correctly loaded
|
||||||
|
- software version in user-agent when fetching feeds is no longer hardcoded
|
||||||
|
- admin settings page is now read only, settings are configured in config.yml
|
||||||
|
- added link to metrics on the admin settings page
|
||||||
|
- Rome (rss library) upgrade to 1.5.0
|
||||||
|
v 2.0.1
|
||||||
|
- the redis pool no longer throws an exception when it is unable to aquire a new connection
|
||||||
|
v2.0.0
|
||||||
|
- The backend has been completely rewritten using Dropwizard instead of TomEE, resulting in a lot less memory consumption and better overall performances.
|
||||||
|
See the README on how to build CommaFeed from now on.
|
||||||
|
- CommaFeed should no longer fetch the same feed multiple times in a row
|
||||||
|
- Users can use their username or email to log in
|
||||||
228
README.md
228
README.md
@@ -1,90 +1,138 @@
|
|||||||
CommaFeed [](https://buildhive.cloudbees.com/job/Athou/job/commafeed/)
|
# CommaFeed [](https://travis-ci.org/Athou/commafeed)
|
||||||
=========
|
|
||||||
Sources for [CommaFeed.com](http://www.commafeed.com/).
|
Sources for [CommaFeed.com](http://www.commafeed.com/).
|
||||||
|
|
||||||
Google Reader inspired self-hosted RSS reader, based on Dropwizard and AngularJS.
|
Google Reader inspired self-hosted RSS reader, based on Dropwizard and AngularJS.
|
||||||
|
|
||||||
Related open-source projects
|
## Related open-source projects
|
||||||
----------------------------
|
|
||||||
|
|
||||||
Android apps: [News+ extension](https://github.com/Athou/commafeed-newsplus) - [Android app](https://github.com/doomrobo/CommaFeed-Android-Reader)
|
Android apps: [News+ extension](https://github.com/Athou/commafeed-newsplus)
|
||||||
|
|
||||||
Browser extensions: [Chrome](https://github.com/Athou/commafeed-chrome) - [Firefox](https://github.com/Athou/commafeed-firefox) - [Opera](https://github.com/Athou/commafeed-opera) - [Safari](https://github.com/Athou/commafeed-safari)
|
Browser extensions: [Chrome](https://github.com/Athou/commafeed-chrome) - [Firefox](https://github.com/Athou/commafeed-firefox) - [Opera](https://github.com/Athou/commafeed-opera) - [Safari](https://github.com/Athou/commafeed-safari)
|
||||||
|
|
||||||
Deployment on your own server
|
## Deployment on your own server
|
||||||
-----------------------------
|
|
||||||
|
### The very short version (download precompiled package)
|
||||||
CommaFeed 2.0 has been rewritten to use Dropwizard and gulp instead of using tomee and wro4j. The latest version of the 1.x branch is available [here](https://github.com/Athou/commafeed/tree/1.x).
|
|
||||||
|
mkdir commafeed && cd commafeed
|
||||||
For storage, you can either use an embedded H2 database or an external MySQL, PostgreSQL or SQLServer database.
|
wget https://github.com/Athou/commafeed/releases/download/2.2.0/commafeed.jar
|
||||||
You also need Maven 3.x (and a Java 1.7+ JDK) installed in order to build the application.
|
wget https://raw.githubusercontent.com/Athou/commafeed/2.2.0/config.yml.example -O config.yml
|
||||||
|
vi config.yml
|
||||||
To install maven and openjdk on Ubuntu, issue the following commands
|
java -Djava.net.preferIPv4Stack=true -jar commafeed.jar server config.yml
|
||||||
|
|
||||||
sudo add-apt-repository ppa:natecarlson/maven3
|
### The short version (build from sources)
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install openjdk-7-jdk maven3
|
git clone https://github.com/Athou/commafeed.git
|
||||||
|
cd commafeed
|
||||||
# Not required but if you don't, use 'mvn3' instead of 'mvn' for the rest of the instructions.
|
./mvnw clean package
|
||||||
sudo ln -s /usr/bin/mvn3 /usr/bin/mvn
|
cp config.yml.example config.yml
|
||||||
|
vi config.yml
|
||||||
On Windows and other operating systems, just download maven 3.x from the [official site](http://maven.apache.org/), extract it somewhere and add the `bin` directory to your `PATH` environment variable.
|
java -Djava.net.preferIPv4Stack=true -jar target/commafeed.jar server config.yml
|
||||||
|
|
||||||
Clone this repository. If you don't have git you can download the sources as a zip file from [here](https://github.com/Athou/commafeed/archive/master.zip)
|
### The long version (same as the short version, but more detailed)
|
||||||
|
|
||||||
git clone https://github.com/Athou/commafeed.git
|
CommaFeed 2.0 has been rewritten to use Dropwizard and gulp instead of using tomee and wro4j. The latest version of the 1.x branch is available [here](https://github.com/Athou/commafeed/tree/1.x).
|
||||||
cd commafeed
|
|
||||||
|
For storage, you can either use an embedded H2 database (use it only to test CommaFeed) or an external MySQL, PostgreSQL or SQLServer database.
|
||||||
Now build the application
|
You also need the Java 1.8+ JDK in order to build the application.
|
||||||
|
|
||||||
mvn clean package
|
To install the required packages to build CommaFeed on Ubuntu, issue the following commands
|
||||||
|
|
||||||
Copy `config.yml.example` to `config.yml` then edit the file to your liking.
|
# if openjdk-8-jdk is not available on your ubuntu version (14.04 LTS), add the following repo first
|
||||||
Issue the following command to run the app, the server will listen by default on ``http://localhost:8082`. The default user is `admin` and the default password is `admin`.
|
sudo add-apt-repository ppa:openjdk-r/ppa
|
||||||
|
sudo apt-get update
|
||||||
java -jar target/commafeed.jar server config.yml
|
|
||||||
|
sudo apt-get install g++ build-essential openjdk-8-jdk
|
||||||
You can use nginx or apache as a proxy http server. Note that when using apache, the `ProxyPreserveHost on` option should be set in your config file.
|
|
||||||
|
# Make sure java8 is the selected java version
|
||||||
Local development
|
sudo update-alternatives --config java
|
||||||
-----------------
|
sudo update-alternatives --config javac
|
||||||
|
|
||||||
To start the dropwizard backend, use your IDE to run CommaFeedApplication as your main class, and pass `server config.dev.yml` as arguments to the program.
|
|
||||||
To start the client-side webserver with watches on assets, run `gulp dev`. The server is now running on port 8082 and is proxying REST requests to dropwizard on port 8083.
|
Clone this repository. If you don't have git you can download the sources as a zip file from [here](https://github.com/Athou/commafeed/archive/master.zip)
|
||||||
|
|
||||||
|
git clone https://github.com/Athou/commafeed.git
|
||||||
Translate CommaFeed into your language
|
cd commafeed
|
||||||
--------------------------------------
|
|
||||||
|
Now build the application
|
||||||
Files for internationalization are located [here](https://github.com/Athou/commafeed/tree/master/src/main/app/i18n).
|
|
||||||
|
./mvnw clean package
|
||||||
To add a new language, create a new file in that directory.
|
|
||||||
The name of the file should be the two-letters [ISO-639-1 language code](http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes).
|
Copy `config.yml.example` to `config.yml` then edit the file to your liking.
|
||||||
The language has to be referenced in the `src/main/app/js/i18n.js` file to be picked up.
|
Issue the following command to run the app, the server will listen by default on `http://localhost:8082`. The default user is `admin` and the default password is `admin`.
|
||||||
|
|
||||||
Themes
|
java -Djava.net.preferIPv4Stack=true -jar target/commafeed.jar server config.yml
|
||||||
---------------------
|
|
||||||
|
You can use a proxy http server such as nginx or apache.
|
||||||
To create a theme, create a new file `src/main/webapp/sass/themes/_<theme>.scss`. Your styles should be wrapped in a `#theme-<theme>` element and use the [SCSS format](http://sass-lang.com/) which is a superset of CSS.
|
|
||||||
|
## Deployment on OpenShift
|
||||||
Don't forget to reference your theme in `src/main/webapp/sass/app.scss` and in `src/main/webapp/js/controllers.js` (look for `$scope.themes`).
|
|
||||||
|
[OpenShift](https://openshift.redhat.com) is Red Hat's Platform-as-a-Service (PaaS) that allows developers to quickly develop, host, and scale applications in a cloud environment. CommaFeed runs perfectly on OpenShift and can even be used in the free tier. Follow the [Getting Started](https://developers.openshift.com/en/getting-started-overview.html) guide and after you sign up and install the Command Line Tools (RHC), do:
|
||||||
See [_test.scss](https://github.com/Athou/commafeed/blob/master/src/main/webapp/sass/themes/_test.scss) for an example.
|
|
||||||
|
rhc create-app commafeed diy-0.1 mysql-5.5
|
||||||
|
cd commafeed
|
||||||
Copyright and license
|
git remote add upstream -m master https://github.com/Athou/commafeed.git
|
||||||
---------------------
|
git pull -s recursive -X theirs upstream master
|
||||||
|
git push
|
||||||
Copyright 2013-2014 CommaFeed.
|
|
||||||
|
# To upgrade an existing openshift installation
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
git pull upstream master
|
||||||
you may not use this work except in compliance with the License.
|
git push
|
||||||
You may obtain a copy of the License in the LICENSE file, or at:
|
|
||||||
|
## Translate CommaFeed into your language
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
Files for internationalization are located [here](https://github.com/Athou/commafeed/tree/master/src/main/app/i18n).
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
To add a new language, create a new file in that directory.
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
The name of the file should be the two-letters [ISO-639-1 language code](http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes).
|
||||||
See the License for the specific language governing permissions and
|
The language has to be referenced in the `src/main/app/js/i18n.js` file to be picked up.
|
||||||
limitations under the License.
|
|
||||||
|
## Themes
|
||||||
|
|
||||||
|
To create a theme, create a new file `src/main/app/sass/themes/_<theme>.scss`. Your styles should be wrapped in a `#theme-<theme>` element and use the [SCSS format](http://sass-lang.com/) which is a superset of CSS.
|
||||||
|
|
||||||
|
Don't forget to reference your theme in `src/main/app/sass/app.scss` and in `src/main/app/js/controllers.js` (look for `$scope.themes`).
|
||||||
|
|
||||||
|
See [_test.scss](https://github.com/Athou/commafeed/blob/master/src/main/app/sass/themes/_test.scss) for an example.
|
||||||
|
|
||||||
|
|
||||||
|
## Local development
|
||||||
|
|
||||||
|
Steps to configuring a development environment for CommaFeed may include, but may not be limited to:
|
||||||
|
|
||||||
|
1. `git clone https://github.com/Athou/CommaFeed` into some folder to get the project files.
|
||||||
|
2. Install Eclipse Luna (or latest) from http://www.eclipse.org/downloads/packages/eclipse-ide-java-developers/lunasr1 or your repo if available.
|
||||||
|
3. In Eclipse, Window → Preferences → Maven → Annotation Processing. Check "Automatically configure JDT APT"
|
||||||
|
* You may have to install the m2e-apt connector to have "Annotation Processing" as an option. Do so from Window → Preferences → Maven → Discovery → Open Catalog → type "m2e-apt" in the search box
|
||||||
|
* If you have installed Eclipse EE instead of Luna, you may have trouble installing m2e-apt
|
||||||
|
4. Install Lombok into Eclipse from http://projectlombok.org/download.html
|
||||||
|
* You may have to run `java -jar lombok.jar` as an administrator if your eclipse installation is not in your home folder
|
||||||
|
5. In Eclipse, File → Import → Maven → Existing Maven Projects. Navigate to where you cloned the CommaFeed files into, and select that as the root directory. Click Finish.
|
||||||
|
* You may notice some errors along the lines of "Plugin execution not covered by lifecycle configuration". These are inconsequential.
|
||||||
|
6. Find the file "CommaFeedApplication.java" under the navigation pane.
|
||||||
|
7. Right click it to bring up the context menu → Debug as... → Debug Configurations
|
||||||
|
8. Type `server config.dev.yml` under "Program arguments" in the "Arguments" tab for the Java Application setting "CommaFeedApplication"
|
||||||
|
9. Apply and hit "Debug"
|
||||||
|
10. The debugger is now working. To connect to it, open a terminal (or command prompt) and navigate to the directory where you cloned the CommaFeed files.
|
||||||
|
11. Issue the command `gulp dev` on Unix based systems or `gulp.cmd dev` in Windows.
|
||||||
|
12. The development server is now running at http://localhost:8082 and is proxying REST requests to dropwizard on port 8083.
|
||||||
|
13. Connect to the server from your browser; you should have functional breakpoints and watches on assets.
|
||||||
|
14. When you're done developing, create a fork at the top of https://github.com/Athou/CommaFeed page and commit your changes to it.
|
||||||
|
15. If you'd like to contribute to CommaFeed, create a pull request from your repository to https://github.com/Athou/CommaFeed when your changes are ready. There's a button to do so at the top of https://github.com/Athou/CommaFeed.
|
||||||
|
|
||||||
|
## Copyright and license
|
||||||
|
|
||||||
|
Copyright 2013-2015 CommaFeed.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this work except in compliance with the License.
|
||||||
|
You may obtain a copy of the License in the LICENSE file, or 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.
|
||||||
|
|||||||
40
bower.json
40
bower.json
@@ -2,32 +2,36 @@
|
|||||||
"name": "commafeed",
|
"name": "commafeed",
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"jquery": "1.11.0",
|
"jquery": "2.1.3",
|
||||||
"jquery-ui": "1.11",
|
"jquery-ui": "1.10.3",
|
||||||
"jquery-mousewheel": "3.1.12",
|
"jquery-mousewheel": "3.1.12",
|
||||||
"lodash": "2.4.1",
|
"lodash": "3.4.0",
|
||||||
"bootstrap": "3.1.1",
|
"bootstrap": "3.3.2",
|
||||||
"font-awesome": "3.2.1",
|
"font-awesome": "3.2.1",
|
||||||
"angular": "1.2.16",
|
"angular": "1.3.14",
|
||||||
"angular-resource": "1.2.16",
|
"angular-resource": "1.3.14",
|
||||||
"angular-route": "1.2.16",
|
"angular-route": "1.3.14",
|
||||||
"angular-sanitize": "1.2.16",
|
"angular-sanitize": "1.3.14",
|
||||||
"angular-touch": "1.2.16",
|
"angular-touch": "1.3.14",
|
||||||
"angular-animate": "1.2.16",
|
"angular-animate": "1.3.14",
|
||||||
"angular-ui-router": "0.2.8",
|
"angular-ui-router": "0.2.13",
|
||||||
"angular-ui-utils": "0.1.0",
|
"angular-ui-utils": "0.1.0",
|
||||||
"angular-ui-select2": "0.0.5",
|
"angular-ui-select2": "0.0.5",
|
||||||
"angular-bootstrap": "0.2.0",
|
"angular-bootstrap": "0.2.0",
|
||||||
"angular-loading-bar": "0.5.0",
|
"angular-loading-bar": "0.6.0",
|
||||||
"angular-translate": "2.2.0",
|
"angular-translate": "2.6.1",
|
||||||
"angular-translate-loader-static-files": "2.2.0",
|
"angular-translate-loader-static-files": "2.6.1",
|
||||||
"ngInfiniteScroll": "1.0.0",
|
"ngInfiniteScroll": "1.0.0",
|
||||||
"ng-grid": "2.0.6",
|
"ng-grid": "2.0.6",
|
||||||
"mousetrap": "1.4.6",
|
"mousetrap": "1.4.6",
|
||||||
"momentjs": "2.6.0",
|
"momentjs": "2.9.0",
|
||||||
"device.js": "matthewhudson/device.js#2ae5c775e35ccc837589e5af34e292c54936778c",
|
"devicejs": "0.2.4",
|
||||||
"readabilicons": "arc90/readability-readabilicons#34c55561c5b8ec6e90714b50237c06b13cb9d59c",
|
"readabilicons": "arc90/readability-readabilicons#34c55561c5b8ec6e90714b50237c06b13cb9d59c",
|
||||||
"zocial": "samcollins/css-social-buttons#1f59ecacde475e563fb6771667597493ec4eecb6",
|
"zocial-less": "1.0.0",
|
||||||
"swagger-ui": "2.0.21"
|
"swagger-ui": "2.1.0"
|
||||||
|
},
|
||||||
|
"resolutions": {
|
||||||
|
"angular": "1.3.14",
|
||||||
|
"angular-translate": "2.6.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,15 @@ app:
|
|||||||
# wether to allow user registrations
|
# wether to allow user registrations
|
||||||
allowRegistrations: true
|
allowRegistrations: true
|
||||||
|
|
||||||
|
# create a demo account the first time the app starts
|
||||||
|
createDemoAccount: false
|
||||||
|
|
||||||
# put your google analytics tracking code here
|
# put your google analytics tracking code here
|
||||||
googleAnalyticsTrackingCode:
|
googleAnalyticsTrackingCode:
|
||||||
|
|
||||||
|
# put your google server key (used for youtube favicon fetching)
|
||||||
|
googleAuthKey:
|
||||||
|
|
||||||
# number of http threads
|
# number of http threads
|
||||||
backgroundThreads: 3
|
backgroundThreads: 3
|
||||||
|
|
||||||
@@ -44,6 +50,9 @@ app:
|
|||||||
# time to keep unread statuses (in days), 0 to disable
|
# time to keep unread statuses (in days), 0 to disable
|
||||||
keepStatusDays: 0
|
keepStatusDays: 0
|
||||||
|
|
||||||
|
# entries to keep per feed, old entries will be deleted, 0 to disable
|
||||||
|
maxFeedCapacity: 500
|
||||||
|
|
||||||
# cache service to use, possible values are 'noop' and 'redis'
|
# cache service to use, possible values are 'noop' and 'redis'
|
||||||
cache: noop
|
cache: noop
|
||||||
|
|
||||||
@@ -66,16 +75,12 @@ app:
|
|||||||
|
|
||||||
database:
|
database:
|
||||||
driverClass: org.h2.Driver
|
driverClass: org.h2.Driver
|
||||||
url: jdbc:h2:./target/example
|
url: jdbc:h2:./target/example;mv_store=false
|
||||||
user: sa
|
user: sa
|
||||||
password: sa
|
password: sa
|
||||||
properties:
|
properties:
|
||||||
charSet: UTF-8
|
charSet: UTF-8
|
||||||
maxWaitForConnection: 1s
|
validationQuery: "/* CommaFeed Health Check */ SELECT 1"
|
||||||
validationQuery: "/* CommaFeed Health Check */ SELECT 1"
|
|
||||||
minSize: 1
|
|
||||||
maxSize: 50
|
|
||||||
checkConnectionWhileIdle: true
|
|
||||||
|
|
||||||
server:
|
server:
|
||||||
applicationConnectors:
|
applicationConnectors:
|
||||||
@@ -84,12 +89,13 @@ server:
|
|||||||
adminConnectors:
|
adminConnectors:
|
||||||
- type: http
|
- type: http
|
||||||
port: 8084
|
port: 8084
|
||||||
|
|
||||||
logging:
|
logging:
|
||||||
level: INFO
|
level: INFO
|
||||||
loggers:
|
loggers:
|
||||||
com.commafeed: DEBUG
|
com.commafeed: DEBUG
|
||||||
liquibase: INFO
|
liquibase: INFO
|
||||||
org.hibernate.SQL: ALL
|
org.hibernate.SQL: INFO # or ALL for sql debugging
|
||||||
org.hibernate.engine.internal.StatisticalLoggingSessionEventListener: WARN
|
org.hibernate.engine.internal.StatisticalLoggingSessionEventListener: WARN
|
||||||
appenders:
|
appenders:
|
||||||
- type: console
|
- type: console
|
||||||
@@ -99,4 +105,16 @@ logging:
|
|||||||
archive: true
|
archive: true
|
||||||
archivedLogFilenamePattern: log/commafeed-%d.log
|
archivedLogFilenamePattern: log/commafeed-%d.log
|
||||||
archivedFileCount: 5
|
archivedFileCount: 5
|
||||||
timeZone: UTC
|
timeZone: UTC
|
||||||
|
|
||||||
|
# Redis pool configuration
|
||||||
|
# (only used if app.cache is 'redis')
|
||||||
|
# -----------------------------------
|
||||||
|
redis:
|
||||||
|
host: localhost
|
||||||
|
port: 6379
|
||||||
|
password:
|
||||||
|
timeout: 2000
|
||||||
|
database: 0
|
||||||
|
maxTotal: 500
|
||||||
|
|
||||||
@@ -7,9 +7,15 @@ app:
|
|||||||
# wether to allow user registrations
|
# wether to allow user registrations
|
||||||
allowRegistrations: false
|
allowRegistrations: false
|
||||||
|
|
||||||
|
# create a demo account the first time the app starts
|
||||||
|
createDemoAccount: false
|
||||||
|
|
||||||
# put your google analytics tracking code here
|
# put your google analytics tracking code here
|
||||||
googleAnalyticsTrackingCode:
|
googleAnalyticsTrackingCode:
|
||||||
|
|
||||||
|
# put your google server key (used for youtube favicon fetching)
|
||||||
|
googleAuthKey:
|
||||||
|
|
||||||
# number of http threads
|
# number of http threads
|
||||||
backgroundThreads: 3
|
backgroundThreads: 3
|
||||||
|
|
||||||
@@ -22,6 +28,7 @@ app:
|
|||||||
smtpTls: false
|
smtpTls: false
|
||||||
smtpUserName:
|
smtpUserName:
|
||||||
smtpPassword:
|
smtpPassword:
|
||||||
|
smtpFromAddress:
|
||||||
|
|
||||||
# wether this commafeed instance has a lot of feeds to refresh
|
# wether this commafeed instance has a lot of feeds to refresh
|
||||||
# leave this to false in almost all cases
|
# leave this to false in almost all cases
|
||||||
@@ -44,6 +51,9 @@ app:
|
|||||||
# time to keep unread statuses (in days), 0 to disable
|
# time to keep unread statuses (in days), 0 to disable
|
||||||
keepStatusDays: 0
|
keepStatusDays: 0
|
||||||
|
|
||||||
|
# entries to keep per feed, old entries will be deleted, 0 to disable
|
||||||
|
maxFeedCapacity: 500
|
||||||
|
|
||||||
# cache service to use, possible values are 'noop' and 'redis'
|
# cache service to use, possible values are 'noop' and 'redis'
|
||||||
cache: noop
|
cache: noop
|
||||||
|
|
||||||
@@ -66,16 +76,15 @@ app:
|
|||||||
|
|
||||||
database:
|
database:
|
||||||
driverClass: org.h2.Driver
|
driverClass: org.h2.Driver
|
||||||
url: jdbc:h2:./target/example
|
url: jdbc:h2:/home/commafeed/db;mv_store=false
|
||||||
user: sa
|
user: sa
|
||||||
password: sa
|
password: sa
|
||||||
properties:
|
properties:
|
||||||
charSet: UTF-8
|
charSet: UTF-8
|
||||||
maxWaitForConnection: 1s
|
validationQuery: "/* CommaFeed Health Check */ SELECT 1"
|
||||||
validationQuery: "/* CommaFeed Health Check */ SELECT 1"
|
minSize: 1
|
||||||
minSize: 1
|
maxSize: 50
|
||||||
maxSize: 50
|
maxConnectionAge: 30m
|
||||||
checkConnectionWhileIdle: true
|
|
||||||
|
|
||||||
server:
|
server:
|
||||||
applicationConnectors:
|
applicationConnectors:
|
||||||
@@ -84,6 +93,7 @@ server:
|
|||||||
adminConnectors:
|
adminConnectors:
|
||||||
- type: http
|
- type: http
|
||||||
port: 8084
|
port: 8084
|
||||||
|
|
||||||
logging:
|
logging:
|
||||||
level: WARN
|
level: WARN
|
||||||
loggers:
|
loggers:
|
||||||
@@ -98,4 +108,16 @@ logging:
|
|||||||
archive: true
|
archive: true
|
||||||
archivedLogFilenamePattern: log/commafeed-%d.log
|
archivedLogFilenamePattern: log/commafeed-%d.log
|
||||||
archivedFileCount: 5
|
archivedFileCount: 5
|
||||||
timeZone: UTC
|
timeZone: UTC
|
||||||
|
|
||||||
|
# Redis pool configuration
|
||||||
|
# (only used if app.cache is 'redis')
|
||||||
|
# -----------------------------------
|
||||||
|
redis:
|
||||||
|
host: localhost
|
||||||
|
port: 6379
|
||||||
|
password:
|
||||||
|
timeout: 2000
|
||||||
|
database: 0
|
||||||
|
maxTotal: 500
|
||||||
|
|
||||||
@@ -1,283 +1,295 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<profiles version="12">
|
<profiles version="12">
|
||||||
<profile kind="CodeFormatterProfile" name="Eclipse [built-in] 140 chars" version="12">
|
<profile kind="CodeFormatterProfile" name="Eclipse [built-in] 140 chars" version="12">
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.compiler.source" value="1.5"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="140"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.5"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="48"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="140"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="48"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.5"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="48"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="48"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="48"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="48"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="140"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.compiler.source" value="1.8"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="48"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.8"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="48"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.8"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="140"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
|
||||||
</profile>
|
</profile>
|
||||||
</profiles>
|
</profiles>
|
||||||
|
|||||||
31
gulpfile.js
31
gulpfile.js
@@ -4,7 +4,6 @@ var revReplace = require('gulp-rev-replace');
|
|||||||
var minifyCSS = require('gulp-minify-css');
|
var minifyCSS = require('gulp-minify-css');
|
||||||
var uglify = require('gulp-uglify');
|
var uglify = require('gulp-uglify');
|
||||||
var filter = require('gulp-filter');
|
var filter = require('gulp-filter');
|
||||||
var bower = require('gulp-bower');
|
|
||||||
var connect = require('gulp-connect');
|
var connect = require('gulp-connect');
|
||||||
var modRewrite = require('connect-modrewrite');
|
var modRewrite = require('connect-modrewrite');
|
||||||
var sass = require('gulp-sass');
|
var sass = require('gulp-sass');
|
||||||
@@ -15,10 +14,6 @@ var SRC_DIR = 'src/main/app/';
|
|||||||
var TEMP_DIR = 'target/gulp/'
|
var TEMP_DIR = 'target/gulp/'
|
||||||
var BUILD_DIR = 'target/classes/assets/';
|
var BUILD_DIR = 'target/classes/assets/';
|
||||||
|
|
||||||
gulp.task('bower', function() {
|
|
||||||
return bower();
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('images', function() {
|
gulp.task('images', function() {
|
||||||
return gulp.src(SRC_DIR + 'images/**/*').pipe(gulp.dest(BUILD_DIR + 'images'));
|
return gulp.src(SRC_DIR + 'images/**/*').pipe(gulp.dest(BUILD_DIR + 'images'));
|
||||||
});
|
});
|
||||||
@@ -27,34 +22,36 @@ gulp.task('i18n', function() {
|
|||||||
return gulp.src(SRC_DIR + 'i18n/**/*.js').pipe(gulp.dest(BUILD_DIR + 'i18n'));
|
return gulp.src(SRC_DIR + 'i18n/**/*.js').pipe(gulp.dest(BUILD_DIR + 'i18n'));
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('favicons', function() {
|
gulp.task('resources', function() {
|
||||||
var favicons_png = SRC_DIR + '*.png';
|
var favicons_png = SRC_DIR + '*.png';
|
||||||
var favicons_ico = SRC_DIR + '*.ico';
|
var favicons_ico = SRC_DIR + '*.ico';
|
||||||
var favicons_svg = SRC_DIR + '*.svg';
|
var favicons_svg = SRC_DIR + '*.svg';
|
||||||
return gulp.src([favicons_png, favicons_ico, favicons_svg]).pipe(gulp.dest(BUILD_DIR));
|
var manifest = SRC_DIR + 'manifest.json';
|
||||||
|
return gulp.src([favicons_png, favicons_ico, favicons_svg, manifest]).pipe(gulp.dest(BUILD_DIR));
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('sass', function() {
|
gulp.task('sass', function() {
|
||||||
return gulp.src(SRC_DIR + 'sass/app.scss').pipe(sass()).pipe(gulp.dest(TEMP_DIR + 'css'));
|
return gulp.src(SRC_DIR + 'sass/app.scss').pipe(sass()).pipe(gulp.dest(TEMP_DIR + 'css'));
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('fonts', ['bower'], function() {
|
gulp.task('fonts', function() {
|
||||||
var font_awesome = SRC_DIR + 'lib/font-awesome/font/fontawesome-webfont.*';
|
var font_awesome = SRC_DIR + 'lib/font-awesome/font/fontawesome-webfont.*';
|
||||||
var zocial = SRC_DIR + 'lib/zocial/css/zocial-regular-*';
|
var zocial = SRC_DIR + 'lib/zocial-less/css/zocial-regular-*';
|
||||||
var readabilicons = SRC_DIR + 'lib/readabilicons/webfont/fonts/readabilicons-*';
|
var readabilicons = SRC_DIR + 'lib/readabilicons/webfont/fonts/readabilicons-*';
|
||||||
return gulp.src([font_awesome, zocial, readabilicons]).pipe(gulp.dest(BUILD_DIR + 'font'));
|
return gulp.src([font_awesome, zocial, readabilicons]).pipe(gulp.dest(BUILD_DIR + 'font'));
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('select2', ['bower'], function() {
|
gulp.task('select2', function() {
|
||||||
var gif = SRC_DIR + 'lib/select2/*.gif';
|
var gif = SRC_DIR + 'lib/select2/*.gif';
|
||||||
var png = SRC_DIR + 'lib/select2/*.png';
|
var png = SRC_DIR + 'lib/select2/*.png';
|
||||||
return gulp.src([gif, png]).pipe(gulp.dest(BUILD_DIR + 'css'));
|
return gulp.src([gif, png]).pipe(gulp.dest(BUILD_DIR + 'css'));
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('swagger-ui', ['bower'], function() {
|
gulp.task('swagger-ui', function() {
|
||||||
var index_html = SRC_DIR + 'api/index.html';
|
var index_html = SRC_DIR + 'api/index.html';
|
||||||
|
var swagger_json = 'target/swagger/swagger.json';
|
||||||
var lib = SRC_DIR + 'lib/swagger-ui/dist/**/*';
|
var lib = SRC_DIR + 'lib/swagger-ui/dist/**/*';
|
||||||
return gulp.src([lib, index_html]).pipe(gulp.dest(BUILD_DIR + 'api'));
|
return gulp.src([lib, index_html, swagger_json]).pipe(gulp.dest(BUILD_DIR + 'api'));
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('template-cache', function() {
|
gulp.task('template-cache', function() {
|
||||||
@@ -65,17 +62,17 @@ gulp.task('template-cache', function() {
|
|||||||
return gulp.src(SRC_DIR + 'templates/**/*.html').pipe(templateCache(options)).pipe(gulp.dest(TEMP_DIR + 'js'));
|
return gulp.src(SRC_DIR + 'templates/**/*.html').pipe(templateCache(options)).pipe(gulp.dest(TEMP_DIR + 'js'));
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('build-dev', ['images', 'i18n', 'favicons', 'sass', 'fonts', 'select2', 'swagger-ui', 'template-cache', 'bower'], function() {
|
gulp.task('build-dev', ['images', 'i18n', 'resources', 'sass', 'fonts', 'select2', 'swagger-ui', 'template-cache'], function() {
|
||||||
var assets = useref.assets({
|
var assets = useref.assets({
|
||||||
searchPath : [SRC_DIR, TEMP_DIR]
|
searchPath : [SRC_DIR, TEMP_DIR]
|
||||||
});
|
});
|
||||||
var jsFilter = filter("**/*.js");
|
var jsFilter = filter("**/*.js");
|
||||||
var cssFilter = filter("**/*.css");
|
var cssFilter = filter("**/*.css");
|
||||||
return gulp.src([SRC_DIR + 'index.html', TEMP_DIR + 'app.css']).pipe(assets).pipe(rev()).pipe(assets.restore()).pipe(useref()).pipe(
|
return gulp.src([SRC_DIR + 'index.html', TEMP_DIR + 'app.css']).pipe(assets).pipe(rev()).pipe(assets.restore()).pipe(useref()).pipe(
|
||||||
revReplace()).pipe(gulp.dest(BUILD_DIR));
|
revReplace()).pipe(gulp.dest(BUILD_DIR)).pipe(connect.reload());
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('build', ['images', 'i18n', 'favicons', 'sass', 'fonts', 'select2', 'swagger-ui', 'template-cache', 'bower'], function() {
|
gulp.task('build', ['images', 'i18n', 'resources', 'sass', 'fonts', 'select2', 'swagger-ui', 'template-cache'], function() {
|
||||||
var assets = useref.assets({
|
var assets = useref.assets({
|
||||||
searchPath : [SRC_DIR, TEMP_DIR]
|
searchPath : [SRC_DIR, TEMP_DIR]
|
||||||
});
|
});
|
||||||
@@ -101,7 +98,9 @@ gulp.task('serve', function() {
|
|||||||
connect.server({
|
connect.server({
|
||||||
root : BUILD_DIR,
|
root : BUILD_DIR,
|
||||||
port : 8082,
|
port : 8082,
|
||||||
|
livereload : true,
|
||||||
middleware : function() {
|
middleware : function() {
|
||||||
|
var api = '^/api/(.*)$ http://localhost:8083/rest/$1 [P]';
|
||||||
var rest = '^/rest/(.*)$ http://localhost:8083/rest/$1 [P]';
|
var rest = '^/rest/(.*)$ http://localhost:8083/rest/$1 [P]';
|
||||||
var next = '^/next(.*)$ http://localhost:8083/next$1 [P]';
|
var next = '^/next(.*)$ http://localhost:8083/next$1 [P]';
|
||||||
var logout = '^/logout$ http://localhost:8083/logout [P]';
|
var logout = '^/logout$ http://localhost:8083/logout [P]';
|
||||||
@@ -113,4 +112,4 @@ gulp.task('serve', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('dev', ['build-dev', 'watch', 'serve']);
|
gulp.task('dev', ['build-dev', 'watch', 'serve']);
|
||||||
gulp.task('default', ['build']);
|
gulp.task('default', ['build']);
|
||||||
|
|||||||
BIN
maven/maven-wrapper.jar
Normal file
BIN
maven/maven-wrapper.jar
Normal file
Binary file not shown.
3
maven/maven-wrapper.properties
Normal file
3
maven/maven-wrapper.properties
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#Maven download properties
|
||||||
|
#Sat Jul 04 09:06:32 CEST 2015
|
||||||
|
distributionUrl=https\://repository.apache.org/content/repositories/releases/org/apache/maven/apache-maven/3.3.3/apache-maven-3.3.3-bin.zip
|
||||||
234
mvnw
vendored
Executable file
234
mvnw
vendored
Executable file
@@ -0,0 +1,234 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
# or more contributor license agreements. See the NOTICE file
|
||||||
|
# distributed with this work for additional information
|
||||||
|
# regarding copyright ownership. The ASF licenses this file
|
||||||
|
# to you 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.
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Maven2 Start Up Batch script
|
||||||
|
#
|
||||||
|
# Required ENV vars:
|
||||||
|
# ------------------
|
||||||
|
# JAVA_HOME - location of a JDK home dir
|
||||||
|
#
|
||||||
|
# Optional ENV vars
|
||||||
|
# -----------------
|
||||||
|
# M2_HOME - location of maven2's installed home dir
|
||||||
|
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||||
|
# e.g. to debug Maven itself, use
|
||||||
|
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||||
|
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
||||||
|
|
||||||
|
if [ -f /etc/mavenrc ] ; then
|
||||||
|
. /etc/mavenrc
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$HOME/.mavenrc" ] ; then
|
||||||
|
. "$HOME/.mavenrc"
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# OS specific support. $var _must_ be set to either true or false.
|
||||||
|
cygwin=false;
|
||||||
|
darwin=false;
|
||||||
|
mingw=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN*) cygwin=true ;;
|
||||||
|
MINGW*) mingw=true;;
|
||||||
|
Darwin*) darwin=true
|
||||||
|
#
|
||||||
|
# Look for the Apple JDKs first to preserve the existing behaviour, and then look
|
||||||
|
# for the new JDKs provided by Oracle.
|
||||||
|
#
|
||||||
|
if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then
|
||||||
|
#
|
||||||
|
# Apple JDKs
|
||||||
|
#
|
||||||
|
export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then
|
||||||
|
#
|
||||||
|
# Apple JDKs
|
||||||
|
#
|
||||||
|
export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then
|
||||||
|
#
|
||||||
|
# Oracle JDKs
|
||||||
|
#
|
||||||
|
export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then
|
||||||
|
#
|
||||||
|
# Apple JDKs
|
||||||
|
#
|
||||||
|
export JAVA_HOME=`/usr/libexec/java_home`
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -z "$JAVA_HOME" ] ; then
|
||||||
|
if [ -r /etc/gentoo-release ] ; then
|
||||||
|
JAVA_HOME=`java-config --jre-home`
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$M2_HOME" ] ; then
|
||||||
|
## resolve links - $0 may be a link to maven's home
|
||||||
|
PRG="$0"
|
||||||
|
|
||||||
|
# need this for relative symlinks
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG="`dirname "$PRG"`/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
saveddir=`pwd`
|
||||||
|
|
||||||
|
M2_HOME=`dirname "$PRG"`/..
|
||||||
|
|
||||||
|
# make it fully qualified
|
||||||
|
M2_HOME=`cd "$M2_HOME" && pwd`
|
||||||
|
|
||||||
|
cd "$saveddir"
|
||||||
|
# echo Using m2 at $M2_HOME
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||||
|
if $cygwin ; then
|
||||||
|
[ -n "$M2_HOME" ] &&
|
||||||
|
M2_HOME=`cygpath --unix "$M2_HOME"`
|
||||||
|
[ -n "$JAVA_HOME" ] &&
|
||||||
|
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||||
|
[ -n "$CLASSPATH" ] &&
|
||||||
|
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Migwn, ensure paths are in UNIX format before anything is touched
|
||||||
|
if $mingw ; then
|
||||||
|
[ -n "$M2_HOME" ] &&
|
||||||
|
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
||||||
|
[ -n "$JAVA_HOME" ] &&
|
||||||
|
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
||||||
|
# TODO classpath?
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$JAVA_HOME" ]; then
|
||||||
|
javaExecutable="`which javac`"
|
||||||
|
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
|
||||||
|
# readlink(1) is not available as standard on Solaris 10.
|
||||||
|
readLink=`which readlink`
|
||||||
|
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
|
||||||
|
if $darwin ; then
|
||||||
|
javaHome="`dirname \"$javaExecutable\"`"
|
||||||
|
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
|
||||||
|
else
|
||||||
|
javaExecutable="`readlink -f \"$javaExecutable\"`"
|
||||||
|
fi
|
||||||
|
javaHome="`dirname \"$javaExecutable\"`"
|
||||||
|
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
|
||||||
|
JAVA_HOME="$javaHome"
|
||||||
|
export JAVA_HOME
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$JAVACMD" ] ; then
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="`which java`"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||||
|
echo " We cannot execute $JAVACMD" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$JAVA_HOME" ] ; then
|
||||||
|
echo "Warning: JAVA_HOME environment variable is not set."
|
||||||
|
fi
|
||||||
|
|
||||||
|
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
|
||||||
|
|
||||||
|
# For Cygwin, switch paths to Windows format before running java
|
||||||
|
if $cygwin; then
|
||||||
|
[ -n "$M2_HOME" ] &&
|
||||||
|
M2_HOME=`cygpath --path --windows "$M2_HOME"`
|
||||||
|
[ -n "$JAVA_HOME" ] &&
|
||||||
|
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
|
||||||
|
[ -n "$CLASSPATH" ] &&
|
||||||
|
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
|
||||||
|
fi
|
||||||
|
|
||||||
|
# traverses directory structure from process work directory to filesystem root
|
||||||
|
# first directory with .mvn subdirectory is considered project base directory
|
||||||
|
find_maven_basedir() {
|
||||||
|
local basedir=$(pwd)
|
||||||
|
local wdir=$(pwd)
|
||||||
|
while [ "$wdir" != '/' ] ; do
|
||||||
|
wdir=$(cd "$wdir/.."; pwd)
|
||||||
|
if [ -d "$wdir"/.mvn ] ; then
|
||||||
|
basedir=$wdir
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo "${basedir}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# concatenates all lines of a file
|
||||||
|
concat_lines() {
|
||||||
|
if [ -f "$1" ]; then
|
||||||
|
echo "$(tr -s '\n' ' ' < "$1")"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)}
|
||||||
|
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||||
|
|
||||||
|
# Provide a "standardized" way to retrieve the CLI args that will
|
||||||
|
# work with both Windows and non-Windows executions.
|
||||||
|
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
|
||||||
|
export MAVEN_CMD_LINE_ARGS
|
||||||
|
|
||||||
|
WRAPPER_LAUNCHER="org.apache.maven.wrapper.MavenWrapperMain"
|
||||||
|
|
||||||
|
exec "$JAVACMD" \
|
||||||
|
$MAVEN_OPTS \
|
||||||
|
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||||
|
-classpath \
|
||||||
|
"$MAVEN_PROJECTBASEDIR/maven/maven-wrapper.jar" \
|
||||||
|
${WRAPPER_LAUNCHER} "$@"
|
||||||
141
mvnw.bat
Normal file
141
mvnw.bat
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
@REM or more contributor license agreements. See the NOTICE file
|
||||||
|
@REM distributed with this work for additional information
|
||||||
|
@REM regarding copyright ownership. The ASF licenses this file
|
||||||
|
@REM to you under the Apache License, Version 2.0 (the
|
||||||
|
@REM "License"); you may not use this file except in compliance
|
||||||
|
@REM with the License. You may obtain a copy of the License at
|
||||||
|
@REM
|
||||||
|
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@REM
|
||||||
|
@REM Unless required by applicable law or agreed to in writing,
|
||||||
|
@REM software distributed under the License is distributed on an
|
||||||
|
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
@REM KIND, either express or implied. See the License for the
|
||||||
|
@REM specific language governing permissions and limitations
|
||||||
|
@REM under the License.
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
@REM Maven2 Start Up Batch script
|
||||||
|
@REM
|
||||||
|
@REM Required ENV vars:
|
||||||
|
@REM JAVA_HOME - location of a JDK home dir
|
||||||
|
@REM
|
||||||
|
@REM Optional ENV vars
|
||||||
|
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||||
|
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
|
||||||
|
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||||
|
@REM e.g. to debug Maven itself, use
|
||||||
|
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||||
|
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||||
|
@echo off
|
||||||
|
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
|
||||||
|
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||||
|
|
||||||
|
@REM set %HOME% to equivalent of $HOME
|
||||||
|
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||||
|
|
||||||
|
@REM Execute a user defined script before this one
|
||||||
|
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||||
|
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||||
|
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
|
||||||
|
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
|
||||||
|
:skipRcPre
|
||||||
|
|
||||||
|
@setlocal
|
||||||
|
|
||||||
|
set ERROR_CODE=0
|
||||||
|
|
||||||
|
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||||
|
@setlocal
|
||||||
|
|
||||||
|
@REM ==== START VALIDATION ====
|
||||||
|
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo Error: JAVA_HOME not found in your environment. >&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||||
|
echo location of your Java installation. >&2
|
||||||
|
echo.
|
||||||
|
goto error
|
||||||
|
|
||||||
|
:OkJHome
|
||||||
|
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||||
|
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||||
|
echo location of your Java installation. >&2
|
||||||
|
echo.
|
||||||
|
goto error
|
||||||
|
|
||||||
|
:init
|
||||||
|
|
||||||
|
set MAVEN_CMD_LINE_ARGS=%*
|
||||||
|
|
||||||
|
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||||
|
@REM Fallback to current working directory if not found.
|
||||||
|
|
||||||
|
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||||
|
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||||
|
|
||||||
|
set EXEC_DIR=%CD%
|
||||||
|
set WDIR=%EXEC_DIR%
|
||||||
|
:findBaseDir
|
||||||
|
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||||
|
cd ..
|
||||||
|
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||||
|
set WDIR=%CD%
|
||||||
|
goto findBaseDir
|
||||||
|
|
||||||
|
:baseDirFound
|
||||||
|
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||||
|
cd "%EXEC_DIR%"
|
||||||
|
goto endDetectBaseDir
|
||||||
|
|
||||||
|
:baseDirNotFound
|
||||||
|
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||||
|
cd "%EXEC_DIR%"
|
||||||
|
|
||||||
|
:endDetectBaseDir
|
||||||
|
|
||||||
|
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||||
|
|
||||||
|
@setlocal EnableExtensions EnableDelayedExpansion
|
||||||
|
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||||
|
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||||
|
|
||||||
|
:endReadAdditionalConfig
|
||||||
|
|
||||||
|
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||||
|
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\maven\maven-wrapper.jar"
|
||||||
|
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||||
|
%MAVEN_JAVA_EXE% -Dmaven.multiModuleProjectDirectory="" %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS%
|
||||||
|
|
||||||
|
if ERRORLEVEL 1 goto error
|
||||||
|
goto end
|
||||||
|
|
||||||
|
:error
|
||||||
|
set ERROR_CODE=1
|
||||||
|
|
||||||
|
:end
|
||||||
|
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||||
|
|
||||||
|
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
|
||||||
|
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||||
|
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
|
||||||
|
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
|
||||||
|
:skipRcPost
|
||||||
|
|
||||||
|
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||||
|
if "%MAVEN_BATCH_PAUSE%" == "on" pause
|
||||||
|
|
||||||
|
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
|
||||||
|
|
||||||
|
exit /B %ERROR_CODE%
|
||||||
24
package.json
24
package.json
@@ -4,17 +4,17 @@
|
|||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"private": true,
|
"private": true,
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"gulp": "3.8.7",
|
"bower": "1.4.1",
|
||||||
"gulp-rev": "1.0.0",
|
"gulp": "3.8.11",
|
||||||
"gulp-rev-replace": "0.3.0",
|
"gulp-rev": "4.0.0",
|
||||||
"gulp-minify-css": "0.3.7",
|
"gulp-rev-replace": "0.4.1",
|
||||||
"gulp-uglify": "0.3.1",
|
"gulp-minify-css": "1.1.5",
|
||||||
"gulp-filter": "1.0.0",
|
"gulp-uglify": "1.2.0",
|
||||||
"gulp-bower": "0.0.6",
|
"gulp-filter": "2.0.2",
|
||||||
"gulp-connect": "2.0.6",
|
"gulp-connect": "2.2.0",
|
||||||
"connect-modrewrite": "0.7.7",
|
"connect-modrewrite": "0.8.1",
|
||||||
"gulp-sass": "0.7.2",
|
"gulp-sass": "2.0.2",
|
||||||
"gulp-useref": "0.6.0",
|
"gulp-useref": "1.1.2",
|
||||||
"gulp-angular-templatecache": "1.3.0"
|
"gulp-angular-templatecache": "1.6.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
296
pom.xml
296
pom.xml
@@ -4,19 +4,29 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>com.commafeed</groupId>
|
<groupId>com.commafeed</groupId>
|
||||||
<artifactId>commafeed</artifactId>
|
<artifactId>commafeed</artifactId>
|
||||||
<version>2.0.0</version>
|
<version>2.3.0</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<name>CommaFeed</name>
|
<name>CommaFeed</name>
|
||||||
|
|
||||||
<prerequisites>
|
<prerequisites>
|
||||||
<maven>3.0.0</maven>
|
<maven>3.1.0</maven>
|
||||||
</prerequisites>
|
</prerequisites>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<dropwizard.version>0.7.1</dropwizard.version>
|
<java.version>1.8</java.version>
|
||||||
|
<dropwizard.version>0.9.1</dropwizard.version>
|
||||||
|
<guice.version>4.0</guice.version>
|
||||||
|
<querydsl.version>4.0.2</querydsl.version>
|
||||||
|
<rome.version>1.5.0</rome.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
<scm>
|
||||||
|
<connection>scm:git:https://github.com/Athou/commafeed.git</connection>
|
||||||
|
<developerConnection>scm:git:https://github.com/Athou/commafeed.git</developerConnection>
|
||||||
|
<url>https://github.com/Athou/commafeed</url>
|
||||||
|
</scm>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<finalName>commafeed</finalName>
|
<finalName>commafeed</finalName>
|
||||||
<resources>
|
<resources>
|
||||||
@@ -25,20 +35,53 @@
|
|||||||
<filtering>true</filtering>
|
<filtering>true</filtering>
|
||||||
</resource>
|
</resource>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
|
<pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.eclipse.m2e</groupId>
|
||||||
|
<artifactId>lifecycle-mapping</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<configuration>
|
||||||
|
<lifecycleMappingMetadata>
|
||||||
|
<pluginExecutions>
|
||||||
|
<pluginExecution>
|
||||||
|
<pluginExecutionFilter>
|
||||||
|
<groupId>com.github.eirslett</groupId>
|
||||||
|
<artifactId>frontend-maven-plugin</artifactId>
|
||||||
|
<versionRange>[0.0.22,)</versionRange>
|
||||||
|
<goals>
|
||||||
|
<goal>npm</goal>
|
||||||
|
<goal>gulp</goal>
|
||||||
|
<goal>bower</goal>
|
||||||
|
</goals>
|
||||||
|
</pluginExecutionFilter>
|
||||||
|
<action>
|
||||||
|
<execute>
|
||||||
|
<runOnIncremental>false</runOnIncremental>
|
||||||
|
</execute>
|
||||||
|
</action>
|
||||||
|
</pluginExecution>
|
||||||
|
</pluginExecutions>
|
||||||
|
</lifecycleMappingMetadata>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</pluginManagement>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.1</version>
|
<version>3.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<source>1.7</source>
|
<source>${java.version}</source>
|
||||||
<target>1.7</target>
|
<target>${java.version}</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>pl.project13.maven</groupId>
|
<groupId>pl.project13.maven</groupId>
|
||||||
<artifactId>git-commit-id-plugin</artifactId>
|
<artifactId>git-commit-id-plugin</artifactId>
|
||||||
<version>2.1.7</version>
|
<version>2.1.13</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<goals>
|
<goals>
|
||||||
@@ -49,6 +92,7 @@
|
|||||||
<configuration>
|
<configuration>
|
||||||
<generateGitPropertiesFile>false</generateGitPropertiesFile>
|
<generateGitPropertiesFile>false</generateGitPropertiesFile>
|
||||||
<failOnNoGitDirectory>false</failOnNoGitDirectory>
|
<failOnNoGitDirectory>false</failOnNoGitDirectory>
|
||||||
|
<failOnUnableToExtractRepoInfo>false</failOnUnableToExtractRepoInfo>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
@@ -85,20 +129,49 @@
|
|||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.github.kongchen</groupId>
|
||||||
|
<artifactId>swagger-maven-plugin</artifactId>
|
||||||
|
<version>3.1.1</version>
|
||||||
|
<configuration>
|
||||||
|
<apiSources>
|
||||||
|
<apiSource>
|
||||||
|
<locations>com.commafeed.frontend.resource;com.commafeed.frontend.model;com.commafeed.frontend.model.request</locations>
|
||||||
|
<swaggerDirectory>target/swagger</swaggerDirectory>
|
||||||
|
<basePath>/rest</basePath>
|
||||||
|
<info>
|
||||||
|
<title>CommaFeed</title>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</info>
|
||||||
|
<typesToSkip>
|
||||||
|
<typeToSkip>com.commafeed.backend.model.User</typeToSkip>
|
||||||
|
</typesToSkip>
|
||||||
|
</apiSource>
|
||||||
|
</apiSources>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>compile</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>generate</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>com.github.eirslett</groupId>
|
<groupId>com.github.eirslett</groupId>
|
||||||
<artifactId>frontend-maven-plugin</artifactId>
|
<artifactId>frontend-maven-plugin</artifactId>
|
||||||
<version>0.0.15</version>
|
<version>0.0.25</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>install node and npm</id>
|
<id>install node and npm</id>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>install-node-and-npm</goal>
|
<goal>install-node-and-npm</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<phase>generate-resources</phase>
|
<phase>compile</phase>
|
||||||
<configuration>
|
<configuration>
|
||||||
<nodeVersion>v0.10.30</nodeVersion>
|
<nodeVersion>v0.10.39</nodeVersion>
|
||||||
<npmVersion>1.3.8</npmVersion>
|
<npmVersion>2.12.1</npmVersion>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
<execution>
|
<execution>
|
||||||
@@ -106,17 +179,42 @@
|
|||||||
<goals>
|
<goals>
|
||||||
<goal>npm</goal>
|
<goal>npm</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<phase>generate-resources</phase>
|
<phase>compile</phase>
|
||||||
|
<configuration>
|
||||||
|
<arguments>install --loglevel info</arguments>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>bower install</id>
|
||||||
|
<goals>
|
||||||
|
<goal>bower</goal>
|
||||||
|
</goals>
|
||||||
|
<phase>compile</phase>
|
||||||
|
<configuration>
|
||||||
|
<arguments>install</arguments>
|
||||||
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
<execution>
|
<execution>
|
||||||
<id>gulp build</id>
|
<id>gulp build</id>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>gulp</goal>
|
<goal>gulp</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<phase>generate-resources</phase>
|
<phase>compile</phase>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>2.6</version>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<manifest>
|
||||||
|
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
|
||||||
|
</manifest>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
@@ -124,30 +222,46 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<version>1.14.4</version>
|
<version>1.16.4</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-api</artifactId>
|
<artifactId>slf4j-api</artifactId>
|
||||||
<version>1.7.7</version>
|
<version>1.7.12</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.inject</groupId>
|
||||||
|
<artifactId>guice</artifactId>
|
||||||
|
<version>${guice.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.inject.extensions</groupId>
|
||||||
|
<artifactId>guice-multibindings</artifactId>
|
||||||
|
<version>${guice.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.dropwizard</groupId>
|
<groupId>io.dropwizard</groupId>
|
||||||
<artifactId>dropwizard-core</artifactId>
|
<artifactId>dropwizard-core</artifactId>
|
||||||
<version>${dropwizard.version}</version>
|
<version>${dropwizard.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.glassfish.hk2.external</groupId>
|
||||||
|
<artifactId>aopalliance-repackaged</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.glassfish.hk2.external</groupId>
|
||||||
|
<artifactId>javax.inject</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.dropwizard</groupId>
|
<groupId>io.dropwizard</groupId>
|
||||||
<artifactId>dropwizard-hibernate</artifactId>
|
<artifactId>dropwizard-hibernate</artifactId>
|
||||||
<version>${dropwizard.version}</version>
|
<version>${dropwizard.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>io.dropwizard</groupId>
|
|
||||||
<artifactId>dropwizard-client</artifactId>
|
|
||||||
<version>${dropwizard.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.dropwizard</groupId>
|
<groupId>io.dropwizard</groupId>
|
||||||
<artifactId>dropwizard-migrations</artifactId>
|
<artifactId>dropwizard-migrations</artifactId>
|
||||||
@@ -159,36 +273,52 @@
|
|||||||
<version>${dropwizard.version}</version>
|
<version>${dropwizard.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.wordnik</groupId>
|
<groupId>io.dropwizard</groupId>
|
||||||
<artifactId>swagger-jaxrs_2.10</artifactId>
|
<artifactId>dropwizard-forms</artifactId>
|
||||||
<version>1.3.7</version>
|
<version>${dropwizard.version}</version>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<artifactId>jsr311-api</artifactId>
|
<groupId>org.glassfish.hk2.external</groupId>
|
||||||
<groupId>javax.ws.rs</groupId>
|
<artifactId>javax.inject</artifactId>
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<artifactId>javassist</artifactId>
|
|
||||||
<groupId>javassist</groupId>
|
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.mysema.querydsl</groupId>
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
<artifactId>httpclient</artifactId>
|
||||||
|
<version>4.5</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>commons-logging</artifactId>
|
||||||
|
<groupId>commons-logging</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.swagger</groupId>
|
||||||
|
<artifactId>swagger-annotations</artifactId>
|
||||||
|
<version>1.5.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.querydsl</groupId>
|
||||||
<artifactId>querydsl-apt</artifactId>
|
<artifactId>querydsl-apt</artifactId>
|
||||||
<version>3.4.2</version>
|
<version>${querydsl.version}</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
<classifier>hibernate</classifier>
|
<classifier>hibernate</classifier>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.mysema.querydsl</groupId>
|
<groupId>com.querydsl</groupId>
|
||||||
<artifactId>querydsl-jpa</artifactId>
|
<artifactId>querydsl-jpa</artifactId>
|
||||||
<version>3.4.2</version>
|
<version>${querydsl.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.sun.jersey.contribs</groupId>
|
<groupId>com.google.guava</groupId>
|
||||||
<artifactId>jersey-multipart</artifactId>
|
<artifactId>guava</artifactId>
|
||||||
<version>1.18.1</version>
|
<version>18.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-io</groupId>
|
<groupId>commons-io</groupId>
|
||||||
@@ -196,92 +326,108 @@
|
|||||||
<version>2.4</version>
|
<version>2.4</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-collections</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-collections</artifactId>
|
<artifactId>commons-collections4</artifactId>
|
||||||
<version>3.2.1</version>
|
<version>4.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-codec</groupId>
|
<groupId>commons-codec</groupId>
|
||||||
<artifactId>commons-codec</artifactId>
|
<artifactId>commons-codec</artifactId>
|
||||||
<version>1.9</version>
|
<version>1.10</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-math</artifactId>
|
<artifactId>commons-math3</artifactId>
|
||||||
<version>2.2</version>
|
<version>3.5</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-jexl</artifactId>
|
||||||
|
<version>2.1.1</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>commons-logging</artifactId>
|
||||||
|
<groupId>commons-logging</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>redis.clients</groupId>
|
<groupId>redis.clients</groupId>
|
||||||
<artifactId>jedis</artifactId>
|
<artifactId>jedis</artifactId>
|
||||||
<version>2.5.2</version>
|
<version>2.7.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.sun.mail</groupId>
|
<groupId>com.sun.mail</groupId>
|
||||||
<artifactId>javax.mail</artifactId>
|
<artifactId>javax.mail</artifactId>
|
||||||
<version>1.5.2</version>
|
<version>1.5.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- upgrade jdom to 2.0.5 for performance reasons (https://github.com/hunterhacker/jdom/issues/112) -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.java.dev.rome</groupId>
|
<groupId>com.rometools</groupId>
|
||||||
<artifactId>rome</artifactId>
|
<artifactId>rome</artifactId>
|
||||||
<version>1.0.0</version>
|
<version>${rome.version}</version>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>jdom</groupId>
|
|
||||||
<artifactId>jdom</artifactId>
|
<artifactId>jdom</artifactId>
|
||||||
|
<groupId>org.jdom</groupId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.rometools</groupId>
|
<groupId>com.rometools</groupId>
|
||||||
<artifactId>rome-opml</artifactId>
|
<artifactId>rome-opml</artifactId>
|
||||||
<version>1.0</version>
|
<version>${rome.version}</version>
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>rome</groupId>
|
|
||||||
<artifactId>rome</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jdom</groupId>
|
<groupId>org.jdom</groupId>
|
||||||
<artifactId>jdom</artifactId>
|
<artifactId>jdom2</artifactId>
|
||||||
<version>1.1.3</version>
|
<version>2.0.6</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jsoup</groupId>
|
<groupId>org.jsoup</groupId>
|
||||||
<artifactId>jsoup</artifactId>
|
<artifactId>jsoup</artifactId>
|
||||||
<version>1.7.3</version>
|
<version>1.8.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.googlecode.juniversalchardet</groupId>
|
<groupId>com.ibm.icu</groupId>
|
||||||
<artifactId>juniversalchardet</artifactId>
|
<artifactId>icu4j</artifactId>
|
||||||
<version>1.0.3</version>
|
<version>55.1</version>
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.google.gwt</groupId>
|
|
||||||
<artifactId>gwt-servlet</artifactId>
|
|
||||||
<version>2.6.1</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.sourceforge.cssparser</groupId>
|
<groupId>net.sourceforge.cssparser</groupId>
|
||||||
<artifactId>cssparser</artifactId>
|
<artifactId>cssparser</artifactId>
|
||||||
<version>0.9.14</version>
|
<version>0.9.16</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.apis</groupId>
|
||||||
|
<artifactId>google-api-services-youtube</artifactId>
|
||||||
|
<version>v3-rev139-1.20.0</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava-jdk5</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.h2database</groupId>
|
<groupId>com.h2database</groupId>
|
||||||
<artifactId>h2</artifactId>
|
<artifactId>h2</artifactId>
|
||||||
<version>1.4.181</version>
|
<version>1.4.190</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>mysql</groupId>
|
<groupId>mysql</groupId>
|
||||||
<artifactId>mysql-connector-java</artifactId>
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
<version>5.1.32</version>
|
<version>5.1.37</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>postgresql</groupId>
|
<groupId>org.postgresql</groupId>
|
||||||
<artifactId>postgresql</artifactId>
|
<artifactId>postgresql</artifactId>
|
||||||
<version>9.1-901-1.jdbc4</version>
|
<version>9.4-1205-jdbc42</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.sourceforge.jtds</groupId>
|
<groupId>net.sourceforge.jtds</groupId>
|
||||||
@@ -292,8 +438,14 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
<version>4.11</version>
|
<version>4.12</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-core</artifactId>
|
||||||
|
<version>2.0.11-beta</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Swagger UI</title>
|
<title>Swagger UI</title>
|
||||||
<link href='//fonts.googleapis.com/css?family=Droid+Sans:400,700' rel='stylesheet' type='text/css'/>
|
<link href='css/typography.css' media='screen' rel='stylesheet' type='text/css'/>
|
||||||
<link href='css/reset.css' media='screen' rel='stylesheet' type='text/css'/>
|
<link href='css/reset.css' media='screen' rel='stylesheet' type='text/css'/>
|
||||||
<link href='css/screen.css' media='screen' rel='stylesheet' type='text/css'/>
|
<link href='css/screen.css' media='screen' rel='stylesheet' type='text/css'/>
|
||||||
<link href='css/reset.css' media='print' rel='stylesheet' type='text/css'/>
|
<link href='css/reset.css' media='print' rel='stylesheet' type='text/css'/>
|
||||||
@@ -12,25 +12,23 @@
|
|||||||
<script src='lib/jquery.slideto.min.js' type='text/javascript'></script>
|
<script src='lib/jquery.slideto.min.js' type='text/javascript'></script>
|
||||||
<script src='lib/jquery.wiggle.min.js' type='text/javascript'></script>
|
<script src='lib/jquery.wiggle.min.js' type='text/javascript'></script>
|
||||||
<script src='lib/jquery.ba-bbq.min.js' type='text/javascript'></script>
|
<script src='lib/jquery.ba-bbq.min.js' type='text/javascript'></script>
|
||||||
<script src='lib/handlebars-1.0.0.js' type='text/javascript'></script>
|
<script src='lib/handlebars-2.0.0.js' type='text/javascript'></script>
|
||||||
<script src='lib/underscore-min.js' type='text/javascript'></script>
|
<script src='lib/underscore-min.js' type='text/javascript'></script>
|
||||||
<script src='lib/backbone-min.js' type='text/javascript'></script>
|
<script src='lib/backbone-min.js' type='text/javascript'></script>
|
||||||
<script src='lib/swagger.js' type='text/javascript'></script>
|
<script src='lib/swagger-client.js' type='text/javascript'></script>
|
||||||
<script src='swagger-ui.js' type='text/javascript'></script>
|
<script src='swagger-ui.js' type='text/javascript'></script>
|
||||||
<script src='lib/highlight.7.3.pack.js' type='text/javascript'></script>
|
<script src='lib/highlight.7.3.pack.js' type='text/javascript'></script>
|
||||||
|
<script src='lib/marked.js' type='text/javascript'></script>
|
||||||
|
|
||||||
<!-- enabling this will enable oauth2 implicit scope support -->
|
<!-- enabling this will enable oauth2 implicit scope support -->
|
||||||
<script src='lib/swagger-oauth.js' type='text/javascript'></script>
|
<script src='lib/swagger-oauth.js' type='text/javascript'></script>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(function () {
|
$(function () {
|
||||||
window.swaggerUi = new SwaggerUi({
|
window.swaggerUi = new SwaggerUi({
|
||||||
url: "../rest/api-docs",
|
url: "./swagger.json",
|
||||||
dom_id: "swagger-ui-container",
|
dom_id: "swagger-ui-container",
|
||||||
supportedSubmitMethods: ['get', 'post', 'put', 'delete'],
|
supportedSubmitMethods: ['get', 'post', 'put', 'delete'],
|
||||||
onComplete: function(swaggerApi, swaggerUi){
|
onComplete: function(swaggerApi, swaggerUi){
|
||||||
log("Loaded SwaggerUI");
|
|
||||||
|
|
||||||
if(typeof initOAuth == "function") {
|
if(typeof initOAuth == "function") {
|
||||||
/*
|
/*
|
||||||
initOAuth({
|
initOAuth({
|
||||||
|
|||||||
BIN
src/main/app/app-icon-192.png
Normal file
BIN
src/main/app/app-icon-192.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.9 KiB |
@@ -98,6 +98,8 @@
|
|||||||
"next_refresh" : "Next refresh",
|
"next_refresh" : "Next refresh",
|
||||||
"queued_for_refresh" : "Queued for refresh",
|
"queued_for_refresh" : "Queued for refresh",
|
||||||
"feed_url" : "Feed URL",
|
"feed_url" : "Feed URL",
|
||||||
|
"filtering_expression" : "Filtering expression",
|
||||||
|
"filtering_expression_help" : "If not empty, an expression evaluating to 'true' or 'false'. If false, new entries for this feed will be marked as read automatically.\nAvailable variables are 'title', 'content', 'url' 'author' and 'categories' and their content is converted to lower case to ease string comparison.\nExample: url.contains('youtube') or (author eq 'athou' and title.contains('github').\nComplete available syntax is available <a href='http://commons.apache.org/proper/commons-jexl/reference/syntax.html' target='_blank'>here</a>.",
|
||||||
"generate_api_key_first" : "Generate an API key in your profile first.",
|
"generate_api_key_first" : "Generate an API key in your profile first.",
|
||||||
"unsubscribe" : "Unsubscribe",
|
"unsubscribe" : "Unsubscribe",
|
||||||
"unsubscribe_confirmation" : "Are you sure you want to unsubscribe from this feed?",
|
"unsubscribe_confirmation" : "Are you sure you want to unsubscribe from this feed?",
|
||||||
|
|||||||
@@ -7,24 +7,26 @@
|
|||||||
"download" : "Descargar",
|
"download" : "Descargar",
|
||||||
"link" : "Enlace",
|
"link" : "Enlace",
|
||||||
"bookmark" : "Marcador",
|
"bookmark" : "Marcador",
|
||||||
"close" : "Close ",
|
"close" : "Cerrar",
|
||||||
"tags" : "Tags "
|
"tags" : "Etiquetas"
|
||||||
},
|
},
|
||||||
"tree" : {
|
"tree" : {
|
||||||
"subscribe" : "Subscribir",
|
"subscribe" : "Suscribirse",
|
||||||
"import" : "Importar",
|
"import" : "Importar",
|
||||||
"new_category" : "Nueva categoría",
|
"new_category" : "Nueva categoría",
|
||||||
"all" : "Todos",
|
"all" : "Todos",
|
||||||
"starred" : "Destacado"
|
"starred" : "Destacados"
|
||||||
},
|
},
|
||||||
"subscribe" : {
|
"subscribe" : {
|
||||||
"feed_url" : "URL del Canal",
|
"feed_url" : "URL del canal",
|
||||||
"feed_name" : "Nombre del Canal",
|
"filtering_expression" : "Expresión de filtrado",
|
||||||
|
"filtering_expression_help" : "Si no está vacía, una expresión se evalúa como 'cierta' o 'falsa'. Si es falsa, las nueva entradas de este canal se marcarán como leídas automáticamente.\nLas variables disponibles son 'title' (título), 'content'(contenido), 'url' (URL), 'author' (autor), y 'categories' (categorías) y sus contenidos son convertidos a minúsculas para facilitar la comparación de strings (cadenas de texto).\nEjemplo: url.contains('youtube') or (author eq 'athou' and title.contains('github').\nLa sintaxis completa está disponible <a href='http://commons.apache.org/proper/commons-jexl/reference/syntax.html' target='_blank'>aquí</a>.",
|
||||||
|
"feed_name" : "Nombre del canal",
|
||||||
"category" : "Categoría"
|
"category" : "Categoría"
|
||||||
},
|
},
|
||||||
"import" : {
|
"import" : {
|
||||||
"google_reader_prefix" : "Déjame importar tus canales de tu",
|
"google_reader_prefix" : "Déjame importar tus canales de tu cuenta ",
|
||||||
"google_reader_suffix" : " cuenta.",
|
"google_reader_suffix" : ".",
|
||||||
"google_download" : "También puedes subir tu archivo subscriptions.xml.",
|
"google_download" : "También puedes subir tu archivo subscriptions.xml.",
|
||||||
"google_download_link" : "Descárgalo de aquí.",
|
"google_download_link" : "Descárgalo de aquí.",
|
||||||
"xml_file" : "Archivo OPML"
|
"xml_file" : "Archivo OPML"
|
||||||
@@ -34,147 +36,147 @@
|
|||||||
"parent" : "Padre"
|
"parent" : "Padre"
|
||||||
},
|
},
|
||||||
"toolbar" : {
|
"toolbar" : {
|
||||||
"unread" : "Sin Leer",
|
"unread" : "No leídos",
|
||||||
"all" : "Todos",
|
"all" : "Todos",
|
||||||
"previous_entry" : "Entrada Anterior",
|
"previous_entry" : "Entrada anterior",
|
||||||
"next_entry" : "Próxima Entrada",
|
"next_entry" : "Entrada siguiente",
|
||||||
"refresh" : "Atualizar",
|
"refresh" : "Atualizar",
|
||||||
"refresh_all" : "Force refresh all my feeds ",
|
"refresh_all" : "Forzar la actualización de todos mis canales.",
|
||||||
"sort_by_asc_desc" : "Ordenar por fecha asc/desc",
|
"sort_by_asc_desc" : "Ordenar por fecha asc/desc.",
|
||||||
"titles_only" : "Sólo Títulos",
|
"titles_only" : "Sólo títulos",
|
||||||
"expanded_view" : "Vista Expandida",
|
"expanded_view" : "Vista expandida",
|
||||||
"mark_all_as_read" : "Marcar todos como leído",
|
"mark_all_as_read" : "Marcar todos como leído",
|
||||||
"mark_all_older_12_hours" : "Items older than 12 hours ",
|
"mark_all_older_12_hours" : "Entradas anteriores a 12 horas.",
|
||||||
"mark_all_older_day" : "Artículos anteriores a un día",
|
"mark_all_older_day" : "Entradas anteriores a un día.",
|
||||||
"mark_all_older_week" : "Artículos más de una semana",
|
"mark_all_older_week" : "Entradas anteriores a una semana.",
|
||||||
"mark_all_older_two_weeks" : "Artículos más de does semanas",
|
"mark_all_older_two_weeks" : "Entradas anteriores a 2 semanas.",
|
||||||
"settings" : "Ajustes",
|
"settings" : "Ajustes",
|
||||||
"profile" : "Perfil",
|
"profile" : "Perfil",
|
||||||
"admin" : "Admin",
|
"admin" : "Admin",
|
||||||
"about" : "Acerca de",
|
"about" : "Acerca de...",
|
||||||
"logout" : "Cerrar sesión",
|
"logout" : "Cerrar sesión",
|
||||||
"donate" : "Donar"
|
"donate" : "Donar"
|
||||||
},
|
},
|
||||||
"view" : {
|
"view" : {
|
||||||
"entry_source" : "from ",
|
"entry_source" : "de ",
|
||||||
"entry_author" : "by ",
|
"entry_author" : "por ",
|
||||||
"error_while_loading_feed" : "Error mientras se cargaba este canal",
|
"error_while_loading_feed" : "Error mientras se cargaba este canal.",
|
||||||
"keep_unread" : "Guardar no leídos",
|
"keep_unread" : "Mantener como no leído.",
|
||||||
"no_unread_items" : "no tiene items sin leer.",
|
"no_unread_items" : "no tiene entradas sin leer.",
|
||||||
"mark_up_to_here" : "Mark as read up to here ",
|
"mark_up_to_here" : "Marcar como leídos hasta aquí.",
|
||||||
"search_for" : "searching for: ",
|
"search_for" : "buscando: ",
|
||||||
"no_search_results" : "No match found for the requested keywords "
|
"no_search_results" : "No se han encontrado resultados para las palabras clave especificadas."
|
||||||
},
|
},
|
||||||
"feedsearch" : {
|
"feedsearch" : {
|
||||||
"hint" : "Type in a subscription... ",
|
"hint" : "Introduce una suscripción...",
|
||||||
"help" : "Use the return key to select and arrow keys to navigate. ",
|
"help" : "Usa la tecla Intro para seleccionar y las teclas de flecha para navegar.",
|
||||||
"result_prefix" : "Your subscriptions: "
|
"result_prefix" : "Tus suscripciones:"
|
||||||
},
|
},
|
||||||
"settings" : {
|
"settings" : {
|
||||||
"general" : {
|
"general" : {
|
||||||
"value" : "General",
|
"value" : "General",
|
||||||
"language" : "Lenguaje",
|
"language" : "Idioma",
|
||||||
"language_contribute" : "Contribuye con traducciones",
|
"language_contribute" : "Contribuye con traducciones.",
|
||||||
"show_unread" : "Mostrar canales y categorías sin entradas no leídas.",
|
"show_unread" : "Mostrar canales y categorías sin entradas no leídas.",
|
||||||
"social_buttons" : "Mostrar botones de compartir de redes sociales.",
|
"social_buttons" : "Mostrar botones para compartir de redes sociales.",
|
||||||
"scroll_marks" : "En vista expandida, el desplazamiento por las entradas las marca como leídas"
|
"scroll_marks" : "En vista expandida, el desplazamiento por las entradas las marca como leídas."
|
||||||
},
|
},
|
||||||
"appearance" : "Appearance ",
|
"appearance" : "Apariencia",
|
||||||
"scroll_speed" : "Scrolling speed when navigating between entries (in milliseconds) ",
|
"scroll_speed" : "Velocidad de desplazamiento al navegar entre entradas (en milisegundos)",
|
||||||
"scroll_speed_help" : "set to 0 to disable ",
|
"scroll_speed_help" : "ponlo a 0 para desactivarlo",
|
||||||
"theme" : "Theme ",
|
"theme" : "Tema",
|
||||||
"submit_your_theme" : "Submit your theme ",
|
"submit_your_theme" : "Envía tu tema ",
|
||||||
"custom_css" : "CSS Personalizado"
|
"custom_css" : "CSS personalizado"
|
||||||
},
|
},
|
||||||
"details" : {
|
"details" : {
|
||||||
"feed_details" : "Detalles de Canales",
|
"feed_details" : "Detalles del canal",
|
||||||
"url" : "URL",
|
"url" : "URL",
|
||||||
"website" : "Website ",
|
"website" : "Sitio web",
|
||||||
"name" : "Nombre",
|
"name" : "Nombre",
|
||||||
"category" : "Categoría",
|
"category" : "Categoría",
|
||||||
"position" : "Position ",
|
"position" : "Posicióon",
|
||||||
"last_refresh" : "Última actualización",
|
"last_refresh" : "Última actualización",
|
||||||
"message" : "Last refresh message ",
|
"message" : "Último mensaje de actualización",
|
||||||
"next_refresh" : "Next refresh ",
|
"next_refresh" : "Próxima actualización",
|
||||||
"queued_for_refresh" : "Queued for refresh ",
|
"queued_for_refresh" : "En cola para actualizar",
|
||||||
"feed_url" : "URL del Canal",
|
"feed_url" : "URL del canal",
|
||||||
"generate_api_key_first" : "Genera una llave API en tu perfil primero.",
|
"generate_api_key_first" : "Genera una clave API en tu perfil primero.",
|
||||||
"unsubscribe" : "Terminar subscripción",
|
"unsubscribe" : "Terminar suscripción",
|
||||||
"unsubscribe_confirmation" : "Are you sure you want to unsubscribe from this feed? ",
|
"unsubscribe_confirmation" : "¿Estás seguro de querer terminar tu suscripción a este canal?",
|
||||||
"delete_category_confirmation" : "Are you sure you want to delete this category? ",
|
"delete_category_confirmation" : "¿Estás seguro de querer eliminar esta categoría?",
|
||||||
"category_details" : "Detalles de la categoría",
|
"category_details" : "Detalles de la categoría",
|
||||||
"tag_details" : "Tag details ",
|
"tag_details" : "Detalles de las etiuqetas ",
|
||||||
"parent_category" : "Categoría principal"
|
"parent_category" : "Categoría principal"
|
||||||
},
|
},
|
||||||
"profile" : {
|
"profile" : {
|
||||||
"user_name" : "Nombre de usuario",
|
"user_name" : "Nombre de usuario",
|
||||||
"email" : "Correo",
|
"email" : "Correo electrónico",
|
||||||
"change_password" : "Cambiar contraseña",
|
"change_password" : "Cambiar contraseña",
|
||||||
"confirm_password" : "Confirmar contraseña",
|
"confirm_password" : "Confirmar contraseña",
|
||||||
"minimum_6_chars" : "Mínimo 6 caracteres",
|
"minimum_6_chars" : "Mínimo 6 caracteres",
|
||||||
"passwords_do_not_match" : "Las contraseñas no coinciden",
|
"passwords_do_not_match" : "Las contraseñas no coinciden",
|
||||||
"api_key" : "Llave API",
|
"api_key" : "Clave API",
|
||||||
"api_key_not_generated" : "No generado todavía",
|
"api_key_not_generated" : "No generado todavía",
|
||||||
"generate_new_api_key" : "Generar nueva llave API",
|
"generate_new_api_key" : "Generar nueva clave API",
|
||||||
"generate_new_api_key_info" : "Al cambiar la contraseña se generará una nueva llave API",
|
"generate_new_api_key_info" : "Al cambiar la contraseña se generará una nueva clave API.",
|
||||||
"opml_export" : "Exportación de OPML",
|
"opml_export" : "Exportación de OPML",
|
||||||
"delete_account" : "Eliminar cuenta",
|
"delete_account" : "Eliminar cuenta",
|
||||||
"delete_account_confirmation" : "Delete your acount? There's no turning back! "
|
"delete_account_confirmation" : "¿Eliminar tu cuenta? ¡No habrá vuelta atrás! "
|
||||||
},
|
},
|
||||||
"about" : {
|
"about" : {
|
||||||
"rest_api" : {
|
"rest_api" : {
|
||||||
"value" : "REST API",
|
"value" : "REST API",
|
||||||
"line1" : "CommaFeed está construido con el uso de JAX-RS y AngularJS. Por eso, un REST API esta disponible.",
|
"line1" : "CommaFeed está construido sobre JAX-RS y AngularJS. Por lo tanto, una REST API está disponible.",
|
||||||
"link_to_documentation" : "Vínculo de la documentación."
|
"link_to_documentation" : "Enlace a la documentación."
|
||||||
},
|
},
|
||||||
"keyboard_shortcuts" : "Atajos de teclado",
|
"keyboard_shortcuts" : "Atajos de teclado",
|
||||||
"version" : "CommaFeed version ",
|
"version" : "Versión de CommaFeed",
|
||||||
"line1_prefix" : "CommaFeed es un proyecto open-source. El código se encuentra en ",
|
"line1_prefix" : "CommaFeed es un proyecto de código abierto. El código se encuentra en ",
|
||||||
"line1_suffix" : ".",
|
"line1_suffix" : ".",
|
||||||
"line2_prefix" : "Si encuentras un problema, por favor reportalo en la página de problemas de ",
|
"line2_prefix" : "Si encuentras un problema, por favor repórtalo en la página de problemas de ",
|
||||||
"line2_suffix" : " del proyecto.",
|
"line2_suffix" : " del proyecto.",
|
||||||
"line3" : "Si te gusta este proyecto, por favor considera realizar una donacion para apoyar al desarrollador y ayudar a cubrir los costos de mantenimiento.",
|
"line3" : "Si te gusta este proyecto, por favor considera realizar una donación para apoyar al desarrollador y ayudar a cubrir los costes de mantenimiento.",
|
||||||
"line4" : "For those of you who prefer bitcoin, here is the address ",
|
"line4" : "Para aquellos de vosotros que prefieran bitcoin, aquí está la dirección ",
|
||||||
"goodies" : {
|
"goodies" : {
|
||||||
"value" : "Goodies",
|
"value" : "Extras",
|
||||||
"android_app" : "Android app ",
|
"android_app" : "Apps para Android",
|
||||||
"subscribe_url" : "Subscribe URL ",
|
"subscribe_url" : "URL para suscribirse ",
|
||||||
"chrome_extension" : "Extensión de Chrome",
|
"chrome_extension" : "Extensión para Chrome.",
|
||||||
"firefox_extension" : "Extensión de Firefox",
|
"firefox_extension" : "Extensión para Firefox.",
|
||||||
"opera_extension" : "Opera extension ",
|
"opera_extension" : "Extensón para Opera.",
|
||||||
"subscribe_bookmarklet" : "Add subscription bookmarklet (click) ",
|
"subscribe_bookmarklet" : "Añadir marcador de suscripción (clic).",
|
||||||
"subscribe_bookmarklet_asc" : "Oldest first ",
|
"subscribe_bookmarklet_asc" : "Más antiguos primero",
|
||||||
"subscribe_bookmarklet_desc" : "Newest first ",
|
"subscribe_bookmarklet_desc" : "Más recientes primero",
|
||||||
"next_unread_bookmarklet" : "Next unread item bookmarklet (drag to bookmark bar) "
|
"next_unread_bookmarklet" : "Marcador a la siguiente entrada no leída (arástralo a la barra de marcadores) "
|
||||||
},
|
},
|
||||||
"translation" : {
|
"translation" : {
|
||||||
"value" : "Traducción",
|
"value" : "Traducción",
|
||||||
"message" : "Necesitamos tu ayuda para ayudar a traducir CommaFeed.",
|
"message" : "Necesitamos tu ayuda para ayudar a traducir CommaFeed.",
|
||||||
"link" : "Ver como contribuir con traducciones."
|
"link" : "Ver cómo contribuir con traducciones."
|
||||||
},
|
},
|
||||||
"announcements" : "Anuncios",
|
"announcements" : "Anuncios",
|
||||||
"shortcuts" : {
|
"shortcuts" : {
|
||||||
"mouse_middleclick" : "ratón botón medio",
|
"mouse_middleclick" : "click medio",
|
||||||
"open_next_entry" : "abrir próxima entrada",
|
"open_next_entry" : "abrir la siguiente entrada",
|
||||||
"open_previous_entry" : "abrir entrada previa",
|
"open_previous_entry" : "abrir la entrada anterior",
|
||||||
"spacebar" : "space/shift+space ",
|
"spacebar" : "espacio/mayúsculas+espacio",
|
||||||
"move_page_down_up" : "moves the page down/up ",
|
"move_page_down_up" : "mueve la página arriba/abajo",
|
||||||
"focus_next_entry" : "Establecer el foco en la próxima entrada sin abrirlo",
|
"focus_next_entry" : "establecer el foco en la siguiente entrada sin abrirla",
|
||||||
"focus_previous_entry" : "Establecer el foco en la entrada anterior sin abrirlo",
|
"focus_previous_entry" : "establecer el foco en la entrada anterior sin abrirla",
|
||||||
"open_next_feed" : "open next feed or category ",
|
"open_next_feed" : "abrir el siguiente canal o categoría",
|
||||||
"open_previous_feed" : "open previous feed or category ",
|
"open_previous_feed" : "abrir el canal o categoría previo",
|
||||||
"open_close_current_entry" : "abrir/cerrar entrada actual",
|
"open_close_current_entry" : "abrir/cerrar la entrada actual",
|
||||||
"open_current_entry_in_new_window" : "abrir entrada actual en una nueva ventana",
|
"open_current_entry_in_new_window" : "abrir la entrada actual en una nueva ventana",
|
||||||
"open_current_entry_in_new_window_background" : "open current entry in a new window in the background ",
|
"open_current_entry_in_new_window_background" : "abrir la entrada actual en una nueva ventana en segundo plano",
|
||||||
"star_unstar" : "marcar/no marcar la entrada actual",
|
"star_unstar" : "destacar la entrada actual",
|
||||||
"mark_current_entry" : "marcar como leída/no la leída entrada actual",
|
"mark_current_entry" : "marcar la entrada actual como leída/no la leída",
|
||||||
"mark_all_as_read" : "marcar todas las entradas como leídas",
|
"mark_all_as_read" : "marcar todas las entradas como leídas",
|
||||||
"open_in_new_tab_mark_as_read" : "abrir entrada en una nueva pestaña y marcar como leída",
|
"open_in_new_tab_mark_as_read" : "abrir entrada en una nueva pestaña y marcar como leída",
|
||||||
"fullscreen" : "toggle full screen mode ",
|
"fullscreen" : "activar/desactivar el modo pantalla completa ",
|
||||||
"font_size" : "increase/decrease font size of the current entry ",
|
"font_size" : "aumentar/reducir el tamaño de la fuente de la entrada actual",
|
||||||
"go_to_all" : "go to the All view ",
|
"go_to_all" : "ver Todos",
|
||||||
"go_to_starred" : "go to the Starred view ",
|
"go_to_starred" : "ver Destacados",
|
||||||
"feed_search" : "navigate to a subscription by entering the subscription name "
|
"feed_search" : "navega a una suscripción al introducir su nombre"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,24 +34,24 @@
|
|||||||
"parent" : "Parent"
|
"parent" : "Parent"
|
||||||
},
|
},
|
||||||
"toolbar" : {
|
"toolbar" : {
|
||||||
"unread" : "Non-lus",
|
"unread" : "Non lus",
|
||||||
"all" : "Tous",
|
"all" : "Tous",
|
||||||
"previous_entry" : "Article précédent",
|
"previous_entry" : "Article précédent",
|
||||||
"next_entry" : "Article suivant",
|
"next_entry" : "Article suivant",
|
||||||
"refresh" : "Rafraîchir",
|
"refresh" : "Rafraîchir",
|
||||||
"refresh_all" : "Force refresh all my feeds ",
|
"refresh_all" : "Rafraîchir tous les flux",
|
||||||
"sort_by_asc_desc" : "Trier par date croissante/décroissante",
|
"sort_by_asc_desc" : "Trier par date croissante/décroissante",
|
||||||
"titles_only" : "Titres uniquement",
|
"titles_only" : "Titres uniquement",
|
||||||
"expanded_view" : "Vue étendue",
|
"expanded_view" : "Vue étendue",
|
||||||
"mark_all_as_read" : "Tout marquer comme lu",
|
"mark_all_as_read" : "Tout marquer comme lu",
|
||||||
"mark_all_older_12_hours" : "Items older than 12 hours ",
|
"mark_all_older_12_hours" : "Articles de plus de 12 heures",
|
||||||
"mark_all_older_day" : "Articles de plus d'un jour",
|
"mark_all_older_day" : "Articles de plus d'une journée",
|
||||||
"mark_all_older_week" : "Articles de plus d'une semaine",
|
"mark_all_older_week" : "Articles de plus d'une semaine",
|
||||||
"mark_all_older_two_weeks" : "Articles de plus d'un mois",
|
"mark_all_older_two_weeks" : "Articles de plus d'un mois",
|
||||||
"settings" : "Préférences",
|
"settings" : "Préférences",
|
||||||
"profile" : "Profil",
|
"profile" : "Profil",
|
||||||
"admin" : "Administration",
|
"admin" : "Administration",
|
||||||
"about" : "A propos",
|
"about" : "À propos",
|
||||||
"logout" : "Déconnexion",
|
"logout" : "Déconnexion",
|
||||||
"donate" : "Faire un don"
|
"donate" : "Faire un don"
|
||||||
},
|
},
|
||||||
@@ -59,16 +59,16 @@
|
|||||||
"entry_source" : "sur",
|
"entry_source" : "sur",
|
||||||
"entry_author" : "par ",
|
"entry_author" : "par ",
|
||||||
"error_while_loading_feed" : "Erreur durant le chargement de ce flux",
|
"error_while_loading_feed" : "Erreur durant le chargement de ce flux",
|
||||||
"keep_unread" : "Garder non-lu",
|
"keep_unread" : "Garder non lu",
|
||||||
"no_unread_items" : "n'a pas d'articles non-lus.",
|
"no_unread_items" : "n'a pas d'articles non lus.",
|
||||||
"mark_up_to_here" : "Marquer comme lu jusqu'ici",
|
"mark_up_to_here" : "Marquer comme lu jusqu'ici",
|
||||||
"search_for" : "searching for: ",
|
"search_for" : "recherche : ",
|
||||||
"no_search_results" : "No match found for the requested keywords "
|
"no_search_results" : "Pas de résultats avec le terme indiqué."
|
||||||
},
|
},
|
||||||
"feedsearch" : {
|
"feedsearch" : {
|
||||||
"hint" : "Tapez un nom de flux",
|
"hint" : "Tapez un nom de flux",
|
||||||
"help" : "Utilisez la touche entrée pour sélectionner et les flèches pour naviguer",
|
"help" : "Utilisez la touche entrée pour sélectionner et les flèches pour naviguer",
|
||||||
"result_prefix" : "Vos flux:"
|
"result_prefix" : "Vos flux :"
|
||||||
},
|
},
|
||||||
"settings" : {
|
"settings" : {
|
||||||
"general" : {
|
"general" : {
|
||||||
@@ -76,12 +76,12 @@
|
|||||||
"language" : "Langue",
|
"language" : "Langue",
|
||||||
"language_contribute" : "Contribuer aux traductions",
|
"language_contribute" : "Contribuer aux traductions",
|
||||||
"show_unread" : "Afficher les flux et les catégories pour lesquels tout est déjà lu",
|
"show_unread" : "Afficher les flux et les catégories pour lesquels tout est déjà lu",
|
||||||
"social_buttons" : "Afficher les boutons de partage sur réseaux sociaux",
|
"social_buttons" : "Afficher les boutons de partage sur les réseaux sociaux",
|
||||||
"scroll_marks" : "En mode de lecture étendu, marquer comme lu les éléments lorsque la fenêtre descend."
|
"scroll_marks" : "En mode de lecture étendu, marquer les éléments comme lus lorsque la fenêtre descend."
|
||||||
},
|
},
|
||||||
"appearance" : "Apparence",
|
"appearance" : "Apparence",
|
||||||
"scroll_speed" : "Scrolling speed when navigating between entries (in milliseconds) ",
|
"scroll_speed" : "Vitesse de défilement entre les entrées (en millisecondes) ",
|
||||||
"scroll_speed_help" : "set to 0 to disable ",
|
"scroll_speed_help" : "Mettez 0 pour désactiver",
|
||||||
"theme" : "Thème",
|
"theme" : "Thème",
|
||||||
"submit_your_theme" : "Soumettez votre thème.",
|
"submit_your_theme" : "Soumettez votre thème.",
|
||||||
"custom_css" : "CSS personnelle"
|
"custom_css" : "CSS personnelle"
|
||||||
@@ -94,16 +94,16 @@
|
|||||||
"category" : "Catégorie",
|
"category" : "Catégorie",
|
||||||
"position" : "Position",
|
"position" : "Position",
|
||||||
"last_refresh" : "Dernière mise à jour",
|
"last_refresh" : "Dernière mise à jour",
|
||||||
"message" : "Last refresh message ",
|
"message" : "Message de la dernière mise à jour ",
|
||||||
"next_refresh" : "Prochaine mise à jour",
|
"next_refresh" : "Prochaine mise à jour",
|
||||||
"queued_for_refresh" : "En file d'attente",
|
"queued_for_refresh" : "En file d'attente",
|
||||||
"feed_url" : "URL du flux",
|
"feed_url" : "URL du flux",
|
||||||
"generate_api_key_first" : "Générez une clé API dans votre profil d'abord.",
|
"generate_api_key_first" : "Générez d'abord une clé API dans votre profil.",
|
||||||
"unsubscribe" : "Se désabonner",
|
"unsubscribe" : "Se désabonner",
|
||||||
"unsubscribe_confirmation" : "Are you sure you want to unsubscribe from this feed? ",
|
"unsubscribe_confirmation" : "Êtes-vous sûr de vouloir vous désabonner de de flux ? ",
|
||||||
"delete_category_confirmation" : "Are you sure you want to delete this category? ",
|
"delete_category_confirmation" : "Êtes-vous sûr de vouloir supprimer cette catégorie ? ",
|
||||||
"category_details" : "Détails de la catégorie",
|
"category_details" : "Détails de la catégorie",
|
||||||
"tag_details" : "Tag details ",
|
"tag_details" : "Détails du tag",
|
||||||
"parent_category" : "Catégorie parente"
|
"parent_category" : "Catégorie parente"
|
||||||
},
|
},
|
||||||
"profile" : {
|
"profile" : {
|
||||||
@@ -116,15 +116,15 @@
|
|||||||
"api_key" : "Clé API",
|
"api_key" : "Clé API",
|
||||||
"api_key_not_generated" : "Pas encore générée",
|
"api_key_not_generated" : "Pas encore générée",
|
||||||
"generate_new_api_key" : "Générer une nouvelle clé API",
|
"generate_new_api_key" : "Générer une nouvelle clé API",
|
||||||
"generate_new_api_key_info" : "Changer de mot de passe va générer une nouvelle clé API",
|
"generate_new_api_key_info" : "Changer de mot de passe générera une nouvelle clé API",
|
||||||
"opml_export" : "Export du fichier OPML",
|
"opml_export" : "Export du fichier OPML",
|
||||||
"delete_account" : "Effacer le compte",
|
"delete_account" : "Effacer le compte",
|
||||||
"delete_account_confirmation" : "Delete your acount? There's no turning back! "
|
"delete_account_confirmation" : "Êtes-vous sûr de vouloir supprimer définitivement votre compte ?"
|
||||||
},
|
},
|
||||||
"about" : {
|
"about" : {
|
||||||
"rest_api" : {
|
"rest_api" : {
|
||||||
"value" : "API REST",
|
"value" : "API REST",
|
||||||
"line1" : "CommaFeed utilise JAX-RS et AngularJS, donc une API REST est disponible.",
|
"line1" : "CommaFeed utilise JAX-RS et AngularJS, une API REST est donc disponible.",
|
||||||
"link_to_documentation" : "Lien vers la documentation."
|
"link_to_documentation" : "Lien vers la documentation."
|
||||||
},
|
},
|
||||||
"keyboard_shortcuts" : "Raccourcis clavier",
|
"keyboard_shortcuts" : "Raccourcis clavier",
|
||||||
@@ -145,7 +145,7 @@
|
|||||||
"subscribe_bookmarklet" : "Bookmarklet d'ajout d'abonnement",
|
"subscribe_bookmarklet" : "Bookmarklet d'ajout d'abonnement",
|
||||||
"subscribe_bookmarklet_asc" : "Du plus ancien au plus récent",
|
"subscribe_bookmarklet_asc" : "Du plus ancien au plus récent",
|
||||||
"subscribe_bookmarklet_desc" : "Du plus récent au plus ancien",
|
"subscribe_bookmarklet_desc" : "Du plus récent au plus ancien",
|
||||||
"next_unread_bookmarklet" : "Bookmarklet vers le prochain article non-lu"
|
"next_unread_bookmarklet" : "Bookmarklet vers le prochain article non lu"
|
||||||
},
|
},
|
||||||
"translation" : {
|
"translation" : {
|
||||||
"value" : "Traduction",
|
"value" : "Traduction",
|
||||||
@@ -165,9 +165,9 @@
|
|||||||
"open_previous_feed" : "Sélectionner le flux ou la catégorie précédente",
|
"open_previous_feed" : "Sélectionner le flux ou la catégorie précédente",
|
||||||
"open_close_current_entry" : "Ouvrir/fermer l'article courant",
|
"open_close_current_entry" : "Ouvrir/fermer l'article courant",
|
||||||
"open_current_entry_in_new_window" : "Ouvrir l'article courant dans une nouvelle fenêtre",
|
"open_current_entry_in_new_window" : "Ouvrir l'article courant dans une nouvelle fenêtre",
|
||||||
"open_current_entry_in_new_window_background" : "Ouvrir l'article courant dans une nouvelle fenêtre en arrière plan",
|
"open_current_entry_in_new_window_background" : "Ouvrir l'article courant dans une nouvelle fenêtre en arrière-plan",
|
||||||
"star_unstar" : "Ajouter/enlever l'article courant des favoris",
|
"star_unstar" : "Ajouter/enlever l'article courant des favoris",
|
||||||
"mark_current_entry" : "Marquer comme lue/non-lue l'article courant",
|
"mark_current_entry" : "Marquer comme lu/non lu l'article courant",
|
||||||
"mark_all_as_read" : "Marquer tous les articles comme lus",
|
"mark_all_as_read" : "Marquer tous les articles comme lus",
|
||||||
"open_in_new_tab_mark_as_read" : "Ouvrir l'article courant dans une nouvelle fenêtre et marquer comme lu",
|
"open_in_new_tab_mark_as_read" : "Ouvrir l'article courant dans une nouvelle fenêtre et marquer comme lu",
|
||||||
"fullscreen" : "Activer/désactiver le mode plein-écran",
|
"fullscreen" : "Activer/désactiver le mode plein-écran",
|
||||||
@@ -177,4 +177,4 @@
|
|||||||
"feed_search" : "Naviguer vers un flux en entrant son nom"
|
"feed_search" : "Naviguer vers un flux en entrant son nom"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
},
|
},
|
||||||
"new_category" : {
|
"new_category" : {
|
||||||
"name" : "Nome",
|
"name" : "Nome",
|
||||||
"parent" : "Pai"
|
"parent" : "Subcategoría de "
|
||||||
},
|
},
|
||||||
"toolbar" : {
|
"toolbar" : {
|
||||||
"unread" : "Sen Ler",
|
"unread" : "Sen Ler",
|
||||||
@@ -39,12 +39,12 @@
|
|||||||
"previous_entry" : "Entrada Anterior",
|
"previous_entry" : "Entrada Anterior",
|
||||||
"next_entry" : "Próxima Entrada",
|
"next_entry" : "Próxima Entrada",
|
||||||
"refresh" : "Actualizar",
|
"refresh" : "Actualizar",
|
||||||
"refresh_all" : "Force refresh all my feeds ",
|
"refresh_all" : "Forzar a actualización de todas as fontes ",
|
||||||
"sort_by_asc_desc" : "Ordenar por data asc/desc",
|
"sort_by_asc_desc" : "Ordenar por data asc/desc",
|
||||||
"titles_only" : "Só títulos",
|
"titles_only" : "Só títulos",
|
||||||
"expanded_view" : "Vista expandida",
|
"expanded_view" : "Vista expandida",
|
||||||
"mark_all_as_read" : "Marcar todos como lidos",
|
"mark_all_as_read" : "Marcar todos como lidos",
|
||||||
"mark_all_older_12_hours" : "Items older than 12 hours ",
|
"mark_all_older_12_hours" : "Elementos anteriores a 12 h. ",
|
||||||
"mark_all_older_day" : "Artigos anteriores a un día",
|
"mark_all_older_day" : "Artigos anteriores a un día",
|
||||||
"mark_all_older_week" : "Artigos de máis de unha semana",
|
"mark_all_older_week" : "Artigos de máis de unha semana",
|
||||||
"mark_all_older_two_weeks" : "Artigos de máis de dúas semanas",
|
"mark_all_older_two_weeks" : "Artigos de máis de dúas semanas",
|
||||||
@@ -56,14 +56,14 @@
|
|||||||
"donate" : "Doar"
|
"donate" : "Doar"
|
||||||
},
|
},
|
||||||
"view" : {
|
"view" : {
|
||||||
"entry_source" : "from ",
|
"entry_source" : "desde ",
|
||||||
"entry_author" : "by ",
|
"entry_author" : "por ",
|
||||||
"error_while_loading_feed" : "Erro mentras se cargaba esta fonte",
|
"error_while_loading_feed" : "Erro mentras se cargaba esta fonte",
|
||||||
"keep_unread" : "Gardar non lidos",
|
"keep_unread" : "Gardar non lidos",
|
||||||
"no_unread_items" : "non ten elementos sen ler.",
|
"no_unread_items" : "non ten elementos sen ler.",
|
||||||
"mark_up_to_here" : "Mark as read up to here ",
|
"mark_up_to_here" : "Marcar como lidos ate aquí ",
|
||||||
"search_for" : "searching for: ",
|
"search_for" : "buscando por: ",
|
||||||
"no_search_results" : "No match found for the requested keywords "
|
"no_search_results" : "Sen coincidencias para as palabras introducidas "
|
||||||
},
|
},
|
||||||
"feedsearch" : {
|
"feedsearch" : {
|
||||||
"hint" : "Escriba unha suscrición...",
|
"hint" : "Escriba unha suscrición...",
|
||||||
@@ -80,8 +80,8 @@
|
|||||||
"scroll_marks" : "En vista expandida, o desplazamento polas entradas márcaas como lidas."
|
"scroll_marks" : "En vista expandida, o desplazamento polas entradas márcaas como lidas."
|
||||||
},
|
},
|
||||||
"appearance" : "Aspecto",
|
"appearance" : "Aspecto",
|
||||||
"scroll_speed" : "Scrolling speed when navigating between entries (in milliseconds) ",
|
"scroll_speed" : "Velocidade de desplazamento navegando entre entradas (en milisegundos) ",
|
||||||
"scroll_speed_help" : "set to 0 to disable ",
|
"scroll_speed_help" : "escriba 0 para deshabilitar ",
|
||||||
"theme" : "Decorado",
|
"theme" : "Decorado",
|
||||||
"submit_your_theme" : "Envíe o seu decorado",
|
"submit_your_theme" : "Envíe o seu decorado",
|
||||||
"custom_css" : "CSS Personalizado"
|
"custom_css" : "CSS Personalizado"
|
||||||
@@ -89,21 +89,21 @@
|
|||||||
"details" : {
|
"details" : {
|
||||||
"feed_details" : "Detalles de fontes",
|
"feed_details" : "Detalles de fontes",
|
||||||
"url" : "URL",
|
"url" : "URL",
|
||||||
"website" : "Website ",
|
"website" : "Sitio web ",
|
||||||
"name" : "Nome",
|
"name" : "Nome",
|
||||||
"category" : "Categoría",
|
"category" : "Categoría",
|
||||||
"position" : "Position ",
|
"position" : "Posición ",
|
||||||
"last_refresh" : "Última actualización",
|
"last_refresh" : "Última actualización",
|
||||||
"message" : "Last refresh message ",
|
"message" : "Última mensaxe da actualización ",
|
||||||
"next_refresh" : "Próxima actualización",
|
"next_refresh" : "Próxima actualización",
|
||||||
"queued_for_refresh" : "En cola para actualizar",
|
"queued_for_refresh" : "En cola para actualizar",
|
||||||
"feed_url" : "URL da fonte",
|
"feed_url" : "URL da fonte",
|
||||||
"generate_api_key_first" : "Antes debes xerar unha chave API no teu perfil.",
|
"generate_api_key_first" : "Antes debes xerar unha chave API no teu perfil.",
|
||||||
"unsubscribe" : "Rematar suscripción",
|
"unsubscribe" : "Rematar suscripción",
|
||||||
"unsubscribe_confirmation" : "Are you sure you want to unsubscribe from this feed? ",
|
"unsubscribe_confirmation" : "Seguro que queres desuscribirte de esta fonte? ",
|
||||||
"delete_category_confirmation" : "Are you sure you want to delete this category? ",
|
"delete_category_confirmation" : "Seguro que queres eliminar esta categoría? ",
|
||||||
"category_details" : "Detalles da categoría",
|
"category_details" : "Detalles da categoría",
|
||||||
"tag_details" : "Tag details ",
|
"tag_details" : "Detalles da etiqueta ",
|
||||||
"parent_category" : "Categoría principal"
|
"parent_category" : "Categoría principal"
|
||||||
},
|
},
|
||||||
"profile" : {
|
"profile" : {
|
||||||
@@ -119,7 +119,7 @@
|
|||||||
"generate_new_api_key_info" : "Ao cambiar o contrasinal xerarase unha nova chave API",
|
"generate_new_api_key_info" : "Ao cambiar o contrasinal xerarase unha nova chave API",
|
||||||
"opml_export" : "Exportación de OPML",
|
"opml_export" : "Exportación de OPML",
|
||||||
"delete_account" : "Eliminar conta",
|
"delete_account" : "Eliminar conta",
|
||||||
"delete_account_confirmation" : "Delete your acount? There's no turning back! "
|
"delete_account_confirmation" : "Eliminar conta? Non hai volta atrás! "
|
||||||
},
|
},
|
||||||
"about" : {
|
"about" : {
|
||||||
"rest_api" : {
|
"rest_api" : {
|
||||||
@@ -158,7 +158,7 @@
|
|||||||
"open_next_entry" : "abrir próxima entrada",
|
"open_next_entry" : "abrir próxima entrada",
|
||||||
"open_previous_entry" : "abrir entrada anterior",
|
"open_previous_entry" : "abrir entrada anterior",
|
||||||
"spacebar" : "space/shift+space ",
|
"spacebar" : "space/shift+space ",
|
||||||
"move_page_down_up" : "moves the page down/up ",
|
"move_page_down_up" : "move a páxina arriba/abaixo ",
|
||||||
"focus_next_entry" : "Establecer o foco na próxima entrada sen abrila",
|
"focus_next_entry" : "Establecer o foco na próxima entrada sen abrila",
|
||||||
"focus_previous_entry" : "Establecer o foco na entrada anterior sen abrila",
|
"focus_previous_entry" : "Establecer o foco na entrada anterior sen abrila",
|
||||||
"open_next_feed" : "abrir a seguinte fonte ou categoría",
|
"open_next_feed" : "abrir a seguinte fonte ou categoría",
|
||||||
@@ -170,11 +170,11 @@
|
|||||||
"mark_current_entry" : "marcar como lida/non lida a entrada actual",
|
"mark_current_entry" : "marcar como lida/non lida a entrada actual",
|
||||||
"mark_all_as_read" : "marcar todas as entradas como lidas",
|
"mark_all_as_read" : "marcar todas as entradas como lidas",
|
||||||
"open_in_new_tab_mark_as_read" : "abrir entrada nunha nova lapela e marcar como lida",
|
"open_in_new_tab_mark_as_read" : "abrir entrada nunha nova lapela e marcar como lida",
|
||||||
"fullscreen" : "toggle full screen mode ",
|
"fullscreen" : "habilita a pantalla completa ",
|
||||||
"font_size" : "increase/decrease font size of the current entry ",
|
"font_size" : "aumenta/diminúe o tamaño da letra da entrada activa ",
|
||||||
"go_to_all" : "go to the All view ",
|
"go_to_all" : "ir a vista TODOS",
|
||||||
"go_to_starred" : "go to the Starred view ",
|
"go_to_starred" : "ir a vista Destacados ",
|
||||||
"feed_search" : "navegue ate unha suscrición introducindo o nome da suscrición"
|
"feed_search" : "navegue ate unha suscrición introducindo o nome da suscrición"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,50 +1,50 @@
|
|||||||
{
|
{
|
||||||
"global" : {
|
"global" : {
|
||||||
"save" : "Salva",
|
"save" : "Salva",
|
||||||
"cancel" : "Cancella",
|
"cancel" : "Annulla",
|
||||||
"delete" : "Elimina",
|
"delete" : "Elimina",
|
||||||
"required" : "Required",
|
"required" : "Richiesto",
|
||||||
"download" : "Download",
|
"download" : "Download",
|
||||||
"link" : "Link",
|
"link" : "Link",
|
||||||
"bookmark" : "Segnalibro ",
|
"bookmark" : "Segnalibro",
|
||||||
"close" : "Chiudi",
|
"close" : "Chiudi",
|
||||||
"tags" : "Tags "
|
"tags" : "Tag"
|
||||||
},
|
},
|
||||||
"tree" : {
|
"tree" : {
|
||||||
"subscribe" : "Iscriviti",
|
"subscribe" : "Iscriviti",
|
||||||
"import" : "Importa",
|
"import" : "Importa",
|
||||||
"new_category" : "Nuova categoria",
|
"new_category" : "Nuova categoria",
|
||||||
"all" : "Tutto",
|
"all" : "Tutti",
|
||||||
"starred" : "Preferiti"
|
"starred" : "Preferiti"
|
||||||
},
|
},
|
||||||
"subscribe" : {
|
"subscribe" : {
|
||||||
"feed_url" : "Feed URL",
|
"feed_url" : "URL feed",
|
||||||
"feed_name" : "Nome Feed",
|
"feed_name" : "Nome feed",
|
||||||
"category" : "Categoria"
|
"category" : "Categoria"
|
||||||
},
|
},
|
||||||
"import" : {
|
"import" : {
|
||||||
"google_reader_prefix" : "Importa i tuoi feed dal tuo ",
|
"google_reader_prefix" : "Permettimi di importare i feed dal tuo account ",
|
||||||
"google_reader_suffix" : " account.",
|
"google_reader_suffix" : ".",
|
||||||
"google_download" : "Oppure, carica il tuo subscriptions.xml",
|
"google_download" : "Oppure carica il tuo file subscriptions.xml.",
|
||||||
"google_download_link" : "Scaricalo da qui",
|
"google_download_link" : "Puoi scaricalo da qui.",
|
||||||
"xml_file" : "OPML File"
|
"xml_file" : "File OPML"
|
||||||
},
|
},
|
||||||
"new_category" : {
|
"new_category" : {
|
||||||
"name" : "Nome",
|
"name" : "Nome",
|
||||||
"parent" : "Parent"
|
"parent" : "Gruppo"
|
||||||
},
|
},
|
||||||
"toolbar" : {
|
"toolbar" : {
|
||||||
"unread" : "Non letti",
|
"unread" : "Non letti",
|
||||||
"all" : "Tutti",
|
"all" : "Tutti",
|
||||||
"previous_entry" : "Precedente",
|
"previous_entry" : "Precedente",
|
||||||
"next_entry" : "Successivo",
|
"next_entry" : "Successivo",
|
||||||
"refresh" : "Ricarica",
|
"refresh" : "Aggiorna",
|
||||||
"refresh_all" : "Force refresh all my feeds ",
|
"refresh_all" : "Forza l'aggiornamento di tutti i feed",
|
||||||
"sort_by_asc_desc" : "Sort by date asc/desc",
|
"sort_by_asc_desc" : "Ordina per data crescente/decrescente",
|
||||||
"titles_only" : "Solo titoli",
|
"titles_only" : "Solo i titoli",
|
||||||
"expanded_view" : "Espandi",
|
"expanded_view" : "Espandi",
|
||||||
"mark_all_as_read" : "Contrassegna tutto come già letto",
|
"mark_all_as_read" : "Segna tutti come già letti",
|
||||||
"mark_all_older_12_hours" : "Items older than 12 hours ",
|
"mark_all_older_12_hours" : "Elementi più vecchi di 12 ore",
|
||||||
"mark_all_older_day" : "Elementi più vecchi di un giorno",
|
"mark_all_older_day" : "Elementi più vecchi di un giorno",
|
||||||
"mark_all_older_week" : "Elementi più vecchi di una settimana",
|
"mark_all_older_week" : "Elementi più vecchi di una settimana",
|
||||||
"mark_all_older_two_weeks" : "Elementi più vecchi di due settimane",
|
"mark_all_older_two_weeks" : "Elementi più vecchi di due settimane",
|
||||||
@@ -52,129 +52,131 @@
|
|||||||
"profile" : "Profilo",
|
"profile" : "Profilo",
|
||||||
"admin" : "Admin",
|
"admin" : "Admin",
|
||||||
"about" : "Informazioni",
|
"about" : "Informazioni",
|
||||||
"logout" : "Logout",
|
"logout" : "Esci",
|
||||||
"donate" : "Dona"
|
"donate" : "Dona"
|
||||||
},
|
},
|
||||||
"view" : {
|
"view" : {
|
||||||
"entry_source" : "from ",
|
"entry_source" : "da",
|
||||||
"entry_author" : "by ",
|
"entry_author" : "di",
|
||||||
"error_while_loading_feed" : "Si è verificato un errore, mentre caricavo il feed",
|
"error_while_loading_feed" : "Si è verificato un errore durante il caricamento del feed",
|
||||||
"keep_unread" : "Mantiene come da leggere",
|
"keep_unread" : "Mantieni come da leggere",
|
||||||
"no_unread_items" : "Non ci sono elementi da leggere.",
|
"no_unread_items" : "non contiene elementi da leggere",
|
||||||
"mark_up_to_here" : "Mark as read up to here ",
|
"mark_up_to_here" : "Segna come letto fin qui",
|
||||||
"search_for" : "searching for: ",
|
"search_for" : "Cerca: ",
|
||||||
"no_search_results" : "No match found for the requested keywords "
|
"no_search_results" : "Nessun risultato per le parole chiave cercate"
|
||||||
},
|
},
|
||||||
"feedsearch" : {
|
"feedsearch" : {
|
||||||
"hint" : "Type in a subscription... ",
|
"hint" : "Digita il nome di una sottoscrizione... ",
|
||||||
"help" : "Use the return key to select and arrow keys to navigate. ",
|
"help" : "Usa il tasto Invio per selezionare e le frecce per navigare.",
|
||||||
"result_prefix" : "Le tue sottoscrizioni"
|
"result_prefix" : "Le tue sottoscrizioni:"
|
||||||
},
|
},
|
||||||
"settings" : {
|
"settings" : {
|
||||||
"general" : {
|
"general" : {
|
||||||
"value" : "Generali",
|
"value" : "Generali",
|
||||||
"language" : "Lingua",
|
"language" : "Lingua",
|
||||||
"language_contribute" : "Contribuisci con le traduzioni",
|
"language_contribute" : "Contribuisci alle traduzioni",
|
||||||
"show_unread" : "Show feeds and categories with no unread entries",
|
"show_unread" : "Mostra i feed e le categorie con voci non lette",
|
||||||
"social_buttons" : "Visualizza i social button",
|
"social_buttons" : "Mostra i pulsanti di condivisione social",
|
||||||
"scroll_marks" : "Marca come letto quando scorri"
|
"scroll_marks" : "In vista estesa, segna come lette le voci che scorri"
|
||||||
},
|
},
|
||||||
"appearance" : "Appearance ",
|
"appearance" : "Aspetto",
|
||||||
"scroll_speed" : "Scrolling speed when navigating between entries (in milliseconds) ",
|
"scroll_speed" : "Velocità di scorrimento quando navighi tra i feed (in millisecondi)",
|
||||||
"scroll_speed_help" : "set to 0 to disable ",
|
"scroll_speed_help" : "Imposta su 0 per disabilitare",
|
||||||
"theme" : "Tema ",
|
"theme" : "Tema",
|
||||||
"submit_your_theme" : "Sottoponi il tuo tema ",
|
"submit_your_theme" : "Sottoponi il tuo tema",
|
||||||
"custom_css" : "Css modificato"
|
"custom_css" : "CSS personalizzato"
|
||||||
},
|
},
|
||||||
"details" : {
|
"details" : {
|
||||||
"feed_details" : "Dettagli feed",
|
"feed_details" : "Dettagli feed",
|
||||||
"url" : "URL",
|
"url" : "URL",
|
||||||
"website" : "Website ",
|
"website" : "Sito web",
|
||||||
"name" : "Nome",
|
"name" : "Nome",
|
||||||
"category" : "Categoria",
|
"category" : "Categoria",
|
||||||
"position" : "Posizione ",
|
"position" : "Posizione",
|
||||||
"last_refresh" : "Ultimo aggiornamento",
|
"last_refresh" : "Ultimo aggiornamento",
|
||||||
"message" : "Last refresh message ",
|
"message" : "Ultimo messaggio di aggiornamento",
|
||||||
"next_refresh" : "Next refresh ",
|
"next_refresh" : "Prossimo aggiornamento",
|
||||||
"queued_for_refresh" : "In attesa per l'aggiornamento ",
|
"queued_for_refresh" : "In coda per l'aggiornamento",
|
||||||
"feed_url" : "Feed URL",
|
"feed_url" : "URL feed",
|
||||||
"generate_api_key_first" : "Generate an API key in your profile first.",
|
"filtering_expression" : "Espressione filtro",
|
||||||
"unsubscribe" : "Annulla l\"'\"iscrizione",
|
"filtering_expression_help" : "Quando non è vuota, l'espressione viene applicata a ogni nuovo elemento e valutata come 'vera' o 'falsa'. Se falsa, l'elemento verrà segnato automaticamente come letto.\nLe variabili accettate sono 'title' (titolo), 'content' (contenuto), 'url', 'author' (autore) e 'categories' (categorie); il loro contenuto è convertito in minuscolo per facilitarne il confronto.\nEsempio: url.contains('youtube') or (author eq 'athou' and title.contains('github')).\nLa sintassi completa è disponibile <a href='http://commons.apache.org/proper/commons-jexl/reference/syntax.html' target='_blank'>qui</a> (in inglese).",
|
||||||
"unsubscribe_confirmation" : "Are you sure you want to unsubscribe from this feed? ",
|
"generate_api_key_first" : "Genera prima una chiave API nelle impostazioni del tuo profilo.",
|
||||||
"delete_category_confirmation" : "Are you sure you want to delete this category? ",
|
"unsubscribe" : "Disiscriviti",
|
||||||
|
"unsubscribe_confirmation" : "Sei sicuro di voler annullare la sottoscrizione al feed?",
|
||||||
|
"delete_category_confirmation" : "Sei sicuro di voler eliminare questa categoria?",
|
||||||
"category_details" : "Dettagli categoria",
|
"category_details" : "Dettagli categoria",
|
||||||
"tag_details" : "Tag details ",
|
"tag_details" : "Dettagli tag",
|
||||||
"parent_category" : "Parent category"
|
"parent_category" : "Categoria principale"
|
||||||
},
|
},
|
||||||
"profile" : {
|
"profile" : {
|
||||||
"user_name" : "User name",
|
"user_name" : "Nome utente",
|
||||||
"email" : "E-mail",
|
"email" : "E-mail",
|
||||||
"change_password" : "Cambia password",
|
"change_password" : "Cambia password",
|
||||||
"confirm_password" : "Conferma password",
|
"confirm_password" : "Conferma password",
|
||||||
"minimum_6_chars" : "Minimo 6 caratteri",
|
"minimum_6_chars" : "Minimo 6 caratteri",
|
||||||
"passwords_do_not_match" : "Le password non corrispondono",
|
"passwords_do_not_match" : "Le password non corrispondono",
|
||||||
"api_key" : "API key",
|
"api_key" : "chiave API",
|
||||||
"api_key_not_generated" : "Non generata ancora",
|
"api_key_not_generated" : "Non ancora generata",
|
||||||
"generate_new_api_key" : "Genera una nuova chiave API",
|
"generate_new_api_key" : "Genera una nuova chiave API",
|
||||||
"generate_new_api_key_info" : "Cambiando la password sarà generata una nuova chiave API",
|
"generate_new_api_key_info" : "Cambiando la password sarà generata una nuova chiave API",
|
||||||
"opml_export" : "Esporta OPML",
|
"opml_export" : "Esporta OPML",
|
||||||
"delete_account" : "Elimina account",
|
"delete_account" : "Elimina account",
|
||||||
"delete_account_confirmation" : "Delete your acount? There's no turning back! "
|
"delete_account_confirmation" : "Vuoi eliminare il tuo account? Non si può tornare indietro!"
|
||||||
},
|
},
|
||||||
"about" : {
|
"about" : {
|
||||||
"rest_api" : {
|
"rest_api" : {
|
||||||
"value" : "REST API",
|
"value" : "REST API",
|
||||||
"line1" : "CommaFeed is built on top of JAX-RS and AngularJS. As such, a REST API is available.",
|
"line1" : "CommaFeed è basato su JAX-RS e AngularJS. Pertanto è disponibile una REST API.",
|
||||||
"link_to_documentation" : "Link alla documentazione."
|
"link_to_documentation" : "Link alla documentazione."
|
||||||
},
|
},
|
||||||
"keyboard_shortcuts" : "Scorciatoie da tastiera",
|
"keyboard_shortcuts" : "Scorciatoie da tastiera",
|
||||||
"version" : "CommaFeed version ",
|
"version" : "Versione di CommaFeed",
|
||||||
"line1_prefix" : "Commefeed è un progetto open-source. I codici sono hostati su ",
|
"line1_prefix" : "CommaFeed è un progetto open source. Trovi i sorgenti su ",
|
||||||
"line1_suffix" : ".",
|
"line1_suffix" : ".",
|
||||||
"line2_prefix" : "Se hai qualche problema, segnalalo sulla pagina del ",
|
"line2_prefix" : "Se hai qualche problema, segnalalo sulla pagina del progetto ",
|
||||||
"line2_suffix" : " progetto.",
|
"line2_suffix" : ".",
|
||||||
"line3" : "Se ti piace il progetto, prendi in considerazione una donazione per supportare lo sviluppatore e contribuire a coprire i costi di mantenenimento di questo sito on-line.",
|
"line3" : "Se ti piace questo progetto, considera una donazione per supportare lo sviluppatore e aiutare a coprire i costi di manutenzione di questo sito.",
|
||||||
"line4" : "Per chi preferisce Bitcoin, questo è l\"'\"indirizzo ",
|
"line4" : "Se preferisci Bitcoin, questo è l'indirizzo",
|
||||||
"goodies" : {
|
"goodies" : {
|
||||||
"value" : "Goodies",
|
"value" : "Cose che potrebbero interessarti",
|
||||||
"android_app" : "Android app ",
|
"android_app" : "Applicazione Android",
|
||||||
"subscribe_url" : "Subscribe URL ",
|
"subscribe_url" : "Sottoscrivi URL",
|
||||||
"chrome_extension" : "Estenzione per Chrome ",
|
"chrome_extension" : "Estensione per Chrome",
|
||||||
"firefox_extension" : "Estensione per Firefox",
|
"firefox_extension" : "Estensione per Firefox",
|
||||||
"opera_extension" : "Estensione per Opera",
|
"opera_extension" : "Estensione per Opera",
|
||||||
"subscribe_bookmarklet" : "Add subscription bookmarklet (click) ",
|
"subscribe_bookmarklet" : "Aggiungi la sottoscrizione ai segnalibri (clicca)",
|
||||||
"subscribe_bookmarklet_asc" : "Oldest first ",
|
"subscribe_bookmarklet_asc" : "Prima i vecchi",
|
||||||
"subscribe_bookmarklet_desc" : "Newest first ",
|
"subscribe_bookmarklet_desc" : "Prima i recenti",
|
||||||
"next_unread_bookmarklet" : "Next unread item bookmarklet (drag to bookmark bar) "
|
"next_unread_bookmarklet" : "Bookmarklet al prossimo elemento da leggere (trascinalo nella barra dei segnalibri)"
|
||||||
},
|
},
|
||||||
"translation" : {
|
"translation" : {
|
||||||
"value" : "Traduzioni",
|
"value" : "Traduzioni",
|
||||||
"message" : "Abbiamo bisogno del tuo aiuto per tradurre CommaFeed.",
|
"message" : "Abbiamo bisogno del tuo aiuto per tradurre CommaFeed.",
|
||||||
"link" : "Vedi come aiutare con le traduzioni."
|
"link" : "Scopri come aiutarci nella traduzioni."
|
||||||
},
|
},
|
||||||
"announcements" : "Annunci",
|
"announcements" : "Annunci",
|
||||||
"shortcuts" : {
|
"shortcuts" : {
|
||||||
"mouse_middleclick" : "mouse middleclick",
|
"mouse_middleclick" : "click centrale del mouse",
|
||||||
"open_next_entry" : "open next entry",
|
"open_next_entry" : "apri successivo",
|
||||||
"open_previous_entry" : "open previous entry",
|
"open_previous_entry" : "apri precedente",
|
||||||
"spacebar" : "space/shift+space ",
|
"spacebar" : "SPAZIO/MAIUSC+SPAZIO",
|
||||||
"move_page_down_up" : "moves the page down/up ",
|
"move_page_down_up" : "muove la pagina in su/giù",
|
||||||
"focus_next_entry" : "set focus on next entry without opening it ",
|
"focus_next_entry" : "metti a fuoco l'elemento successivo senza aprirlo",
|
||||||
"focus_previous_entry" : "set focus on previous entry without opening it ",
|
"focus_previous_entry" : "metti a fuoco l'elemento precedente senza aprirlo",
|
||||||
"open_next_feed" : "open next feed or category ",
|
"open_next_feed" : "apri il prossimo feed o categoria",
|
||||||
"open_previous_feed" : "open previous feed or category ",
|
"open_previous_feed" : "apri il feed o la categoria precedente",
|
||||||
"open_close_current_entry" : "open/close current entry",
|
"open_close_current_entry" : "apri/chiudi la voce corrente",
|
||||||
"open_current_entry_in_new_window" : "open current entry in a new window",
|
"open_current_entry_in_new_window" : "apri la voce corrente in una nuova finestra",
|
||||||
"open_current_entry_in_new_window_background" : "open current entry in a new window in the background ",
|
"open_current_entry_in_new_window_background" : "apri la voce corrente in una nuova finestra in secondo piano",
|
||||||
"star_unstar" : "star/unstar current entry",
|
"star_unstar" : "metti/togli la tua preferenza alla voce corrente",
|
||||||
"mark_current_entry" : "mark as read/unread current entry",
|
"mark_current_entry" : "segna la voce corrente come letta/non letta",
|
||||||
"mark_all_as_read" : "mark all entries as read",
|
"mark_all_as_read" : "segna tutte le voci come lette",
|
||||||
"open_in_new_tab_mark_as_read" : "open entry in new tab and mark as read",
|
"open_in_new_tab_mark_as_read" : "apri voce in un nuovo tab e segna come letta",
|
||||||
"fullscreen" : "toggle full screen mode ",
|
"fullscreen" : "commuta la modalità a schermo intero",
|
||||||
"font_size" : "increase/decrease font size of the current entry ",
|
"font_size" : "aumenta/decrementa la dimensione del font per la voce corrente",
|
||||||
"go_to_all" : "go to the All view ",
|
"go_to_all" : "vai alla vista Tutti",
|
||||||
"go_to_starred" : "go to the Starred view ",
|
"go_to_starred" : "vai alla vista Preferiti",
|
||||||
"feed_search" : "navigate to a subscription by entering the subscription name "
|
"feed_search" : "raggiungi una sottoscrizione scrivendo il suo nome"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
"link" : "Bağlantı",
|
"link" : "Bağlantı",
|
||||||
"bookmark" : "Yer imi",
|
"bookmark" : "Yer imi",
|
||||||
"close" : "Kapat",
|
"close" : "Kapat",
|
||||||
"tags" : "Tags "
|
"tags" : "Etiketler "
|
||||||
},
|
},
|
||||||
"tree" : {
|
"tree" : {
|
||||||
"subscribe" : "Abone ol",
|
"subscribe" : "Abone ol",
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
},
|
},
|
||||||
"import" : {
|
"import" : {
|
||||||
"google_reader_prefix" : "Aboneliklerinizi ",
|
"google_reader_prefix" : "Aboneliklerinizi ",
|
||||||
"google_reader_suffix" : " hesabınızdan aktarmama izin verin.",
|
"google_reader_suffix" : "Hesabınızdan aktarmama izin verin.",
|
||||||
"google_download" : "Veya, subscriptions.xml dosyanızı yükleyin.",
|
"google_download" : "Veya, subscriptions.xml dosyanızı yükleyin.",
|
||||||
"google_download_link" : "Buradan indirebilirsiniz.",
|
"google_download_link" : "Buradan indirebilirsiniz.",
|
||||||
"xml_file" : "OPML dosyası"
|
"xml_file" : "OPML dosyası"
|
||||||
@@ -39,15 +39,15 @@
|
|||||||
"previous_entry" : "Önceki ileti",
|
"previous_entry" : "Önceki ileti",
|
||||||
"next_entry" : "Sonraki ileti",
|
"next_entry" : "Sonraki ileti",
|
||||||
"refresh" : "Yenile",
|
"refresh" : "Yenile",
|
||||||
"refresh_all" : "Force refresh all my feeds ",
|
"refresh_all" : "Tüm yayınları yenilemek için zorla",
|
||||||
"sort_by_asc_desc" : "Tarihe göre sırala artan/azalan",
|
"sort_by_asc_desc" : "Tarihe göre sırala artan/azalan",
|
||||||
"titles_only" : "Sadece başlıklar",
|
"titles_only" : "Sadece başlıklar",
|
||||||
"expanded_view" : "Genişletilmiş görünüm",
|
"expanded_view" : "Genişletilmiş görünüm",
|
||||||
"mark_all_as_read" : "Tümünü okundu işaretle",
|
"mark_all_as_read" : "Tümünü okundu işaretle",
|
||||||
"mark_all_older_12_hours" : "Items older than 12 hours ",
|
"mark_all_older_12_hours" : "12 saatten daha eski yayınlar ",
|
||||||
"mark_all_older_day" : "Bir günden eski yazılar",
|
"mark_all_older_day" : "Bir günden eski yayınlar",
|
||||||
"mark_all_older_week" : "Bir haftadan eski yazılar",
|
"mark_all_older_week" : "Bir haftadan eski yayınlar",
|
||||||
"mark_all_older_two_weeks" : "İki haftadan eski yazılar",
|
"mark_all_older_two_weeks" : "İki haftadan eski yayınlar",
|
||||||
"settings" : "Ayarlar",
|
"settings" : "Ayarlar",
|
||||||
"profile" : "Profil",
|
"profile" : "Profil",
|
||||||
"admin" : "Yönetim",
|
"admin" : "Yönetim",
|
||||||
@@ -56,14 +56,14 @@
|
|||||||
"donate" : "Bağış"
|
"donate" : "Bağış"
|
||||||
},
|
},
|
||||||
"view" : {
|
"view" : {
|
||||||
"entry_source" : "from ",
|
"entry_source" : "kaynak: ",
|
||||||
"entry_author" : "by ",
|
"entry_author" : "yazar: ",
|
||||||
"error_while_loading_feed" : "Bu aboneliği çekerken hata oluştu.",
|
"error_while_loading_feed" : "Bu aboneliği çekerken hata oluştu.",
|
||||||
"keep_unread" : "Okunmadı olarak sakla",
|
"keep_unread" : "Okunmadı olarak sakla",
|
||||||
"no_unread_items" : "okunmamış ileti yok.",
|
"no_unread_items" : "Okunmamış ileti yok.",
|
||||||
"mark_up_to_here" : "Mark as read up to here ",
|
"mark_up_to_here" : "Buraya kadar olan bütün yayınları okundu olarak işaretle!",
|
||||||
"search_for" : "searching for: ",
|
"search_for" : "searching for: ",
|
||||||
"no_search_results" : "No match found for the requested keywords "
|
"no_search_results" : "İstenen anahtar kelimeler için eşleşme bulunamadı"
|
||||||
},
|
},
|
||||||
"feedsearch" : {
|
"feedsearch" : {
|
||||||
"hint" : "Bir abonelik yazın...",
|
"hint" : "Bir abonelik yazın...",
|
||||||
@@ -80,8 +80,8 @@
|
|||||||
"scroll_marks" : "Genişletilmiş görünümde götüntülenen iletileri okunmuş işaretle"
|
"scroll_marks" : "Genişletilmiş görünümde götüntülenen iletileri okunmuş işaretle"
|
||||||
},
|
},
|
||||||
"appearance" : "Görünüm",
|
"appearance" : "Görünüm",
|
||||||
"scroll_speed" : "Scrolling speed when navigating between entries (in milliseconds) ",
|
"scroll_speed" : "İçerikler arasında gezinirken kaydırma hızı (milisaniye cinsinden)",
|
||||||
"scroll_speed_help" : "set to 0 to disable ",
|
"scroll_speed_help" : "ayarı kapatmak için 0 yazınız",
|
||||||
"theme" : "Tema",
|
"theme" : "Tema",
|
||||||
"submit_your_theme" : "Tema gönder",
|
"submit_your_theme" : "Tema gönder",
|
||||||
"custom_css" : "Kişiselleştirilmiş CSS"
|
"custom_css" : "Kişiselleştirilmiş CSS"
|
||||||
@@ -100,10 +100,10 @@
|
|||||||
"feed_url" : "Yayın URL'si",
|
"feed_url" : "Yayın URL'si",
|
||||||
"generate_api_key_first" : "Öncelikle profilinizden bir API anahtarı oluşturun.",
|
"generate_api_key_first" : "Öncelikle profilinizden bir API anahtarı oluşturun.",
|
||||||
"unsubscribe" : "Aboneliği iptal et",
|
"unsubscribe" : "Aboneliği iptal et",
|
||||||
"unsubscribe_confirmation" : "Are you sure you want to unsubscribe from this feed? ",
|
"unsubscribe_confirmation" : "Bu yayından çıkmak istediğinizden emin misiniz? ",
|
||||||
"delete_category_confirmation" : "Are you sure you want to delete this category? ",
|
"delete_category_confirmation" : "Bu kategoriyi silmek istediğinizden emin misiniz? ",
|
||||||
"category_details" : "Kategori detayları",
|
"category_details" : "Kategori detayları",
|
||||||
"tag_details" : "Tag details ",
|
"tag_details" : "Etiket detayları ",
|
||||||
"parent_category" : "Üst kategori"
|
"parent_category" : "Üst kategori"
|
||||||
},
|
},
|
||||||
"profile" : {
|
"profile" : {
|
||||||
@@ -116,10 +116,10 @@
|
|||||||
"api_key" : "API anahtarı",
|
"api_key" : "API anahtarı",
|
||||||
"api_key_not_generated" : "Henüz oluşturulmadı",
|
"api_key_not_generated" : "Henüz oluşturulmadı",
|
||||||
"generate_new_api_key" : "Yeni bir API anahtarı oluştur",
|
"generate_new_api_key" : "Yeni bir API anahtarı oluştur",
|
||||||
"generate_new_api_key_info" : "Şifre değiştirmek API anahtarının da değiştirilmesine neden olcak.",
|
"generate_new_api_key_info" : "Şifreyi değiştirmek API anahtarının da değiştirilmesine neden olcak.",
|
||||||
"opml_export" : "OPML dışa aktar",
|
"opml_export" : "OPML dışa aktar",
|
||||||
"delete_account" : "Hesabı sil",
|
"delete_account" : "Hesabı sil",
|
||||||
"delete_account_confirmation" : "Delete your acount? There's no turning back! "
|
"delete_account_confirmation" : "Hesabı silmek istediğinize emin misiniz? Bu işlemde geri dönüş yoktur! "
|
||||||
},
|
},
|
||||||
"about" : {
|
"about" : {
|
||||||
"rest_api" : {
|
"rest_api" : {
|
||||||
@@ -128,24 +128,24 @@
|
|||||||
"link_to_documentation" : "Dökümantasyon için tıklayın."
|
"link_to_documentation" : "Dökümantasyon için tıklayın."
|
||||||
},
|
},
|
||||||
"keyboard_shortcuts" : "Klavye kısayolları",
|
"keyboard_shortcuts" : "Klavye kısayolları",
|
||||||
"version" : "CommaFeed version ",
|
"version" : "CommaFeed versiyon ",
|
||||||
"line1_prefix" : "CommaFeed bir açık kaynak projedir. Kaynak dosyaları ",
|
"line1_prefix" : "CommaFeed bir açık kaynak projedir. Kaynak dosyaları ",
|
||||||
"line1_suffix" : " adresinde yayınlanır.",
|
"line1_suffix" : "adresinde yayınlanır.",
|
||||||
"line2_prefix" : "Lütfen, bir hata ile karşılaşırsanız bunu ",
|
"line2_prefix" : "Lütfen, bir hata ile karşılaşırsanız bunu ",
|
||||||
"line2_suffix" : " projesinde hatalar sayfasından rapor edin.",
|
"line2_suffix" : "projesinde hatalar sayfasından rapor edin.",
|
||||||
"line3" : "Eğer bu projeyi beğendiyseniz, lütfen bağış yaparak geliştiriciye bu sayfayı ayakta tutmasında yardımcı olun.",
|
"line3" : "Eğer bu projeyi beğendiyseniz, lütfen bağış yaparak geliştiriciye bu sayfayı ayakta tutmasında yardımcı olun.",
|
||||||
"line4" : "Bitcoin'i tercih edenler için adres ",
|
"line4" : "Bitcoin'i tercih edenler için adres ",
|
||||||
"goodies" : {
|
"goodies" : {
|
||||||
"value" : "Extralar",
|
"value" : "Ekstralar",
|
||||||
"android_app" : "Android app ",
|
"android_app" : "Android eklentisi",
|
||||||
"subscribe_url" : "Abonelik URL'si",
|
"subscribe_url" : "Abonelik URL'si",
|
||||||
"chrome_extension" : "Chrome eklentisi",
|
"chrome_extension" : "Chrome eklentisi",
|
||||||
"firefox_extension" : "Firefox eklentisi",
|
"firefox_extension" : "Firefox eklentisi",
|
||||||
"opera_extension" : "Opera eklentisi",
|
"opera_extension" : "Opera eklentisi",
|
||||||
"subscribe_bookmarklet" : "Bookmarklet'a abonelik ekle (tıklayın)",
|
"subscribe_bookmarklet" : "Yer imilerine abonelik ekle (tıklayın)",
|
||||||
"subscribe_bookmarklet_asc" : "Oldest first ",
|
"subscribe_bookmarklet_asc" : "Eskiler önce",
|
||||||
"subscribe_bookmarklet_desc" : "Newest first ",
|
"subscribe_bookmarklet_desc" : "Yeniler önce ",
|
||||||
"next_unread_bookmarklet" : "Bookmarklet'daki en son okunmamış ileti (Sık kullanılan çubuğuna sürükleyin)"
|
"next_unread_bookmarklet" : "Yer imilerindeki en son okunmamış ileti (Sık kullanılan çubuğuna sürükleyin)"
|
||||||
},
|
},
|
||||||
"translation" : {
|
"translation" : {
|
||||||
"value" : "Çeviri",
|
"value" : "Çeviri",
|
||||||
@@ -158,7 +158,7 @@
|
|||||||
"open_next_entry" : "sonraki öğeyi görüntüle",
|
"open_next_entry" : "sonraki öğeyi görüntüle",
|
||||||
"open_previous_entry" : "önceki öğeyi görüntüle",
|
"open_previous_entry" : "önceki öğeyi görüntüle",
|
||||||
"spacebar" : "space/shift+space ",
|
"spacebar" : "space/shift+space ",
|
||||||
"move_page_down_up" : "moves the page down/up ",
|
"move_page_down_up" : "sayfayı aşağı/yukarı hareket ettir",
|
||||||
"focus_next_entry" : "sonraki öğeyi görüntülemeden işaretle",
|
"focus_next_entry" : "sonraki öğeyi görüntülemeden işaretle",
|
||||||
"focus_previous_entry" : "önceki öğeyi görüntülemeden işaretle",
|
"focus_previous_entry" : "önceki öğeyi görüntülemeden işaretle",
|
||||||
"open_next_feed" : "sonraki aboneliği veya kategoriyi görüntüle",
|
"open_next_feed" : "sonraki aboneliği veya kategoriyi görüntüle",
|
||||||
@@ -170,11 +170,11 @@
|
|||||||
"mark_current_entry" : "görüntülenen öğeyi okundu/okunmadı işaretle",
|
"mark_current_entry" : "görüntülenen öğeyi okundu/okunmadı işaretle",
|
||||||
"mark_all_as_read" : "tümünü okundu işaretle",
|
"mark_all_as_read" : "tümünü okundu işaretle",
|
||||||
"open_in_new_tab_mark_as_read" : "öğeyi yeni bir sekmede aç ve okundu işaretle",
|
"open_in_new_tab_mark_as_read" : "öğeyi yeni bir sekmede aç ve okundu işaretle",
|
||||||
"fullscreen" : "toggle full screen mode ",
|
"fullscreen" : "tam ekran moduna geç ",
|
||||||
"font_size" : "increase/decrease font size of the current entry ",
|
"font_size" : "mevcut içerik için yazı boyunutunu arttır/azalt",
|
||||||
"go_to_all" : "go to the All view ",
|
"go_to_all" : "Tüm öğeleri görüntüle",
|
||||||
"go_to_starred" : "go to the Starred view ",
|
"go_to_starred" : "yıldızlı öğerleri görüntüle",
|
||||||
"feed_search" : "abonelik ismini yazarak aboneliğe git"
|
"feed_search" : "abonelik ismini yazarak aboneliğe git"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.0 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 21 KiB |
@@ -4,6 +4,10 @@
|
|||||||
<title>CommaFeed</title>
|
<title>CommaFeed</title>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||||
|
<meta name="mobile-web-app-capable" content="yes">
|
||||||
|
<link rel="manifest" href="manifest.json">
|
||||||
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
|
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
|
||||||
<link rel="apple-touch-icon" href="app-icon-57.png" />
|
<link rel="apple-touch-icon" href="app-icon-57.png" />
|
||||||
<link rel="apple-touch-icon" sizes="72x72" href="app-icon-72.png" />
|
<link rel="apple-touch-icon" sizes="72x72" href="app-icon-72.png" />
|
||||||
@@ -12,7 +16,9 @@
|
|||||||
<link rel="icon" sizes="32x32" href="app-icon-32.png" />
|
<link rel="icon" sizes="32x32" href="app-icon-32.png" />
|
||||||
<link rel="icon" sizes="64x64" href="app-icon-64.png" />
|
<link rel="icon" sizes="64x64" href="app-icon-64.png" />
|
||||||
<link rel="icon" sizes="128x128" href="app-icon-128.png" />
|
<link rel="icon" sizes="128x128" href="app-icon-128.png" />
|
||||||
|
<link rel="icon" sizes="192x192" href="app-icon-192.png" />
|
||||||
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
|
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
|
||||||
|
<meta name="theme-color" content="#F88A14" />
|
||||||
<meta name="application-name" content="CommaFeed" />
|
<meta name="application-name" content="CommaFeed" />
|
||||||
<meta name="msapplication-navbutton-color" content="#F88A14" />
|
<meta name="msapplication-navbutton-color" content="#F88A14" />
|
||||||
<meta name="msapplication-starturl" content="/" />
|
<meta name="msapplication-starturl" content="/" />
|
||||||
@@ -26,7 +32,7 @@
|
|||||||
<link rel="stylesheet" href="lib/font-awesome/css/font-awesome.css" />
|
<link rel="stylesheet" href="lib/font-awesome/css/font-awesome.css" />
|
||||||
<link rel="stylesheet" href="lib/select2/select2.css" />
|
<link rel="stylesheet" href="lib/select2/select2.css" />
|
||||||
<link rel="stylesheet" href="lib/ng-grid/ng-grid.css" />
|
<link rel="stylesheet" href="lib/ng-grid/ng-grid.css" />
|
||||||
<link rel="stylesheet" href="lib/jquery-ui/themes/smoothness/jquery-ui.css" />
|
<link rel="stylesheet" href="lib/jquery-ui/themes/base/jquery-ui.css" />
|
||||||
<link rel="stylesheet" href="lib/angular-loading-bar/build/loading-bar.css" />
|
<link rel="stylesheet" href="lib/angular-loading-bar/build/loading-bar.css" />
|
||||||
|
|
||||||
<link rel="stylesheet" href="css/app.css" />
|
<link rel="stylesheet" href="css/app.css" />
|
||||||
@@ -39,9 +45,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- build:js js/app.js -->
|
<!-- build:js js/app.js -->
|
||||||
<script type="text/javascript" src="lib/lodash/dist/lodash.js"></script>
|
<script type="text/javascript" src="lib/lodash/lodash.js"></script>
|
||||||
<script type="text/javascript" src="lib/jquery/dist/jquery.js"></script>
|
<script type="text/javascript" src="lib/jquery/dist/jquery.js"></script>
|
||||||
<script type="text/javascript" src="lib/jquery-ui/jquery-ui.js"></script>
|
<script type="text/javascript" src="lib/jquery-ui/ui/jquery-ui.js"></script>
|
||||||
<script type="text/javascript" src="lib/jquery-mousewheel/jquery.mousewheel.js"></script>
|
<script type="text/javascript" src="lib/jquery-mousewheel/jquery.mousewheel.js"></script>
|
||||||
<script type="text/javascript" src="lib/bootstrap/dist/js/bootstrap.js"></script>
|
<script type="text/javascript" src="lib/bootstrap/dist/js/bootstrap.js"></script>
|
||||||
<script type="text/javascript" src="lib/angular/angular.js"></script>
|
<script type="text/javascript" src="lib/angular/angular.js"></script>
|
||||||
@@ -62,8 +68,8 @@
|
|||||||
<script type="text/javascript" src="lib/angular-ui-select2/src/select2.js"></script>
|
<script type="text/javascript" src="lib/angular-ui-select2/src/select2.js"></script>
|
||||||
<script type="text/javascript" src="lib/select2/select2.js"></script>
|
<script type="text/javascript" src="lib/select2/select2.js"></script>
|
||||||
<script type="text/javascript" src="lib/mousetrap/mousetrap.js"></script>
|
<script type="text/javascript" src="lib/mousetrap/mousetrap.js"></script>
|
||||||
<script type="text/javascript" src="lib/momentjs/min/moment-with-langs.js"></script>
|
<script type="text/javascript" src="lib/momentjs/min/moment-with-locales.js"></script>
|
||||||
<script type="text/javascript" src="lib/device.js/lib/device.js"></script>
|
<script type="text/javascript" src="lib/devicejs/lib/device.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="js/controllers.js"></script>
|
<script type="text/javascript" src="js/controllers.js"></script>
|
||||||
<script type="text/javascript" src="js/directives.js"></script>
|
<script type="text/javascript" src="js/directives.js"></script>
|
||||||
|
|||||||
@@ -322,17 +322,21 @@ module.controller('FeedDetailsCtrl', ['$scope', '$state', '$stateParams', 'FeedS
|
|||||||
|
|
||||||
$scope.save = function() {
|
$scope.save = function() {
|
||||||
var sub = $scope.sub;
|
var sub = $scope.sub;
|
||||||
|
$scope.error = null;
|
||||||
FeedService.modify({
|
FeedService.modify({
|
||||||
id : sub.id,
|
id : sub.id,
|
||||||
name : sub.name,
|
name : sub.name,
|
||||||
position : sub.position,
|
position : sub.position,
|
||||||
categoryId : sub.categoryId
|
categoryId : sub.categoryId,
|
||||||
|
filter : sub.filter
|
||||||
}, function() {
|
}, function() {
|
||||||
CategoryService.init();
|
CategoryService.init();
|
||||||
$state.transitionTo('feeds.view', {
|
$state.transitionTo('feeds.view', {
|
||||||
_id : 'all',
|
_id : 'all',
|
||||||
_type : 'category'
|
_type : 'category'
|
||||||
});
|
});
|
||||||
|
}, function(e) {
|
||||||
|
$scope.error = e.data;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}]);
|
}]);
|
||||||
@@ -489,6 +493,7 @@ module.controller('ToolbarCtrl', [
|
|||||||
type : $stateParams._type,
|
type : $stateParams._type,
|
||||||
id : $stateParams._id,
|
id : $stateParams._id,
|
||||||
olderThan : olderThan,
|
olderThan : olderThan,
|
||||||
|
keywords : $location.search().q,
|
||||||
read : true
|
read : true
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -881,6 +886,7 @@ module.controller('FeedListCtrl', [
|
|||||||
service.mark({
|
service.mark({
|
||||||
id : $scope.selectedId,
|
id : $scope.selectedId,
|
||||||
olderThan : olderThan || $scope.timestamp,
|
olderThan : olderThan || $scope.timestamp,
|
||||||
|
keywords : $location.search().q,
|
||||||
read : true
|
read : true
|
||||||
}, function() {
|
}, function() {
|
||||||
CategoryService.refresh(function() {
|
CategoryService.refresh(function() {
|
||||||
@@ -1365,7 +1371,7 @@ module.controller('SettingsCtrl', ['$scope', '$location', 'SettingsService', 'An
|
|||||||
|
|
||||||
$scope.langs = LangService.langs;
|
$scope.langs = LangService.langs;
|
||||||
|
|
||||||
$scope.themes = ['default', 'bootstrap', 'dark', 'ebraminio', 'MRACHINI', 'svetla', 'third'];
|
$scope.themes = ['default', 'bootstrap', 'dark', 'ebraminio', 'MRACHINI', 'nightsky', 'svetla', 'third'];
|
||||||
|
|
||||||
$scope.settingsService = SettingsService;
|
$scope.settingsService = SettingsService;
|
||||||
$scope.$watch('settingsService.settings', function(value) {
|
$scope.$watch('settingsService.settings', function(value) {
|
||||||
@@ -1432,6 +1438,9 @@ module.controller('ManageSettingsCtrl', ['$scope', '$location', '$state', 'Admin
|
|||||||
$scope.toUsers = function() {
|
$scope.toUsers = function() {
|
||||||
$state.transitionTo('admin.userlist');
|
$state.transitionTo('admin.userlist');
|
||||||
};
|
};
|
||||||
|
$scope.toMetrics = function() {
|
||||||
|
$state.transitionTo('admin.metrics');
|
||||||
|
};
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
module.controller('HelpController', ['$scope', 'CategoryService', 'AnalyticsService', 'ServerService',
|
module.controller('HelpController', ['$scope', 'CategoryService', 'AnalyticsService', 'ServerService',
|
||||||
@@ -1460,55 +1469,58 @@ module.controller('MetricsCtrl', ['$scope', 'AdminMetricsService', function($sco
|
|||||||
$scope.metrics = AdminMetricsService.get();
|
$scope.metrics = AdminMetricsService.get();
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
module.controller('LoginCtrl', ['$scope', '$location', 'SessionService', 'ServerService', function($scope, $location, SessionService, ServerService) {
|
module.controller('LoginCtrl', ['$scope', '$location', '$timeout', 'SessionService', 'ServerService',
|
||||||
$scope.model = {};
|
function($scope, $location, $timeout, SessionService, ServerService) {
|
||||||
$scope.recovery_model = {};
|
$scope.model = {};
|
||||||
$scope.recovery = false;
|
$scope.recovery_model = {};
|
||||||
$scope.recovery_enabled = false;
|
$scope.recovery = false;
|
||||||
|
$scope.recovery_enabled = false;
|
||||||
ServerService.get(function(data) {
|
|
||||||
$scope.recovery_enabled = data.smtpEnabled;
|
|
||||||
});
|
|
||||||
|
|
||||||
var login = function(model) {
|
|
||||||
var success = function(data) {
|
|
||||||
window.location.href = window.location.href.substring(0, window.location.href.lastIndexOf('#'));
|
|
||||||
};
|
|
||||||
var error = function(data) {
|
|
||||||
$scope.message = data.data;
|
|
||||||
};
|
|
||||||
SessionService.login({
|
|
||||||
name : model.name,
|
|
||||||
password : model.password
|
|
||||||
}, success, error);
|
|
||||||
}
|
|
||||||
$scope.demoLogin = function() {
|
|
||||||
login({
|
|
||||||
name : 'demo',
|
|
||||||
password : 'demo'
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.login = function() {
|
ServerService.get(function(data) {
|
||||||
login($scope.model);
|
$scope.recovery_enabled = data.smtpEnabled;
|
||||||
};
|
});
|
||||||
|
|
||||||
$scope.toggleRecovery = function() {
|
var login = function(model) {
|
||||||
$scope.recovery = !$scope.recovery;
|
var success = function(data) {
|
||||||
};
|
window.location.href = window.location.href.substring(0, window.location.href.lastIndexOf('#'));
|
||||||
|
};
|
||||||
var recovery_success = function(data) {
|
var error = function(data) {
|
||||||
$scope.recovery_message = "Email has ben sent. Check your inbox.";
|
$scope.message = data.data;
|
||||||
};
|
};
|
||||||
var recovery_error = function(data) {
|
SessionService.login({
|
||||||
$scope.recovery_message = data.data;
|
name : model.name,
|
||||||
};
|
password : model.password
|
||||||
$scope.recover = function() {
|
}, success, error);
|
||||||
SessionService.passwordReset({
|
}
|
||||||
email : $scope.recovery_model.email
|
$scope.demoLogin = function() {
|
||||||
}, recovery_success, recovery_error);
|
login({
|
||||||
}
|
name : 'demo',
|
||||||
}]);
|
password : 'demo'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.login = function() {
|
||||||
|
// autofilled fields do not trigger model update, do it manually
|
||||||
|
$('input[ng-model]').trigger('input');
|
||||||
|
login($scope.model);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.toggleRecovery = function() {
|
||||||
|
$scope.recovery = !$scope.recovery;
|
||||||
|
};
|
||||||
|
|
||||||
|
var recovery_success = function(data) {
|
||||||
|
$scope.recovery_message = "Email has ben sent. Check your inbox.";
|
||||||
|
};
|
||||||
|
var recovery_error = function(data) {
|
||||||
|
$scope.recovery_message = data.data;
|
||||||
|
};
|
||||||
|
$scope.recover = function() {
|
||||||
|
SessionService.passwordReset({
|
||||||
|
email : $scope.recovery_model.email
|
||||||
|
}, recovery_success, recovery_error);
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
|
||||||
module.controller('RegisterCtrl', ['$scope', '$location', 'SessionService', 'ServerService',
|
module.controller('RegisterCtrl', ['$scope', '$location', 'SessionService', 'ServerService',
|
||||||
function($scope, $location, SessionService, ServerService) {
|
function($scope, $location, SessionService, ServerService) {
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ module.directive('tags', function() {
|
|||||||
tags : []
|
tags : []
|
||||||
};
|
};
|
||||||
if (newValue) {
|
if (newValue) {
|
||||||
data.tags = newValue.split(',');
|
data.tags = newValue;
|
||||||
}
|
}
|
||||||
EntryService.tag(data);
|
EntryService.tag(data);
|
||||||
}
|
}
|
||||||
@@ -193,7 +193,7 @@ module.directive('category', [function() {
|
|||||||
});
|
});
|
||||||
var label = '';
|
var label = '';
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
label = '(' + count + ')';
|
label += count;
|
||||||
}
|
}
|
||||||
return label;
|
return label;
|
||||||
};
|
};
|
||||||
@@ -201,7 +201,7 @@ module.directive('category', [function() {
|
|||||||
$scope.feedCountLabel = function(feed) {
|
$scope.feedCountLabel = function(feed) {
|
||||||
var label = '';
|
var label = '';
|
||||||
if (feed.unread > 0) {
|
if (feed.unread > 0) {
|
||||||
label = '(' + feed.unread + ')';
|
label += feed.unread;
|
||||||
}
|
}
|
||||||
return label;
|
return label;
|
||||||
};
|
};
|
||||||
@@ -308,7 +308,8 @@ module.directive('droppable', ['CategoryService', 'FeedService', function(Catego
|
|||||||
|
|
||||||
var data = {
|
var data = {
|
||||||
id : source.id,
|
id : source.id,
|
||||||
name : source.name
|
name : source.name,
|
||||||
|
filter : source.filter
|
||||||
};
|
};
|
||||||
|
|
||||||
if (source.children) {
|
if (source.children) {
|
||||||
@@ -358,4 +359,15 @@ module.directive('metricGauge', function() {
|
|||||||
restrict : 'E',
|
restrict : 'E',
|
||||||
templateUrl : 'templates/_metrics.gauge.html'
|
templateUrl : 'templates/_metrics.gauge.html'
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
module.directive('metricTimer', function() {
|
||||||
|
return {
|
||||||
|
scope : {
|
||||||
|
metric : '=',
|
||||||
|
label : '='
|
||||||
|
},
|
||||||
|
restrict : 'E',
|
||||||
|
templateUrl : 'templates/_metrics.timer.html'
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ module.service('LangService', [function() {
|
|||||||
'nn': 'Norsk (nynorsk)',
|
'nn': 'Norsk (nynorsk)',
|
||||||
'pt': 'Português',
|
'pt': 'Português',
|
||||||
'pl': 'Polski',
|
'pl': 'Polski',
|
||||||
'ru': 'русский',
|
'ru': 'Русский',
|
||||||
'fi': 'Suomi',
|
'fi': 'Suomi',
|
||||||
'sv': 'Svenska',
|
'sv': 'Svenska',
|
||||||
'zh': '简体中文',
|
'zh': '简体中文',
|
||||||
@@ -31,4 +31,4 @@ module.service('LangService', [function() {
|
|||||||
'cs': 'Čeština',
|
'cs': 'Čeština',
|
||||||
'ms': 'Bahasa Malaysian'
|
'ms': 'Bahasa Malaysian'
|
||||||
}
|
}
|
||||||
}]);
|
}]);
|
||||||
|
|||||||
@@ -12,10 +12,9 @@ app.config([
|
|||||||
'$translateProvider',
|
'$translateProvider',
|
||||||
function($routeProvider, $stateProvider, $urlRouterProvider, $httpProvider, $compileProvider, cfpLoadingBarProvider,
|
function($routeProvider, $stateProvider, $urlRouterProvider, $httpProvider, $compileProvider, cfpLoadingBarProvider,
|
||||||
$translateProvider) {
|
$translateProvider) {
|
||||||
|
|
||||||
// $translateProvider.useLocalStorage();
|
|
||||||
$translateProvider.useStaticFilesLoader({
|
$translateProvider.useStaticFilesLoader({
|
||||||
prefix : '/i18n/',
|
prefix : 'i18n/',
|
||||||
suffix : '.js'
|
suffix : '.js'
|
||||||
});
|
});
|
||||||
$translateProvider.preferredLanguage('en');
|
$translateProvider.preferredLanguage('en');
|
||||||
@@ -24,26 +23,23 @@ app.config([
|
|||||||
|
|
||||||
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|javascript):/);
|
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|javascript):/);
|
||||||
var interceptor = ['$rootScope', '$q', '$injector', function(scope, $q, $injector) {
|
var interceptor = ['$rootScope', '$q', '$injector', function(scope, $q, $injector) {
|
||||||
|
var f = {};
|
||||||
var success = function(response) {
|
|
||||||
|
f.response = function(response) {
|
||||||
return response;
|
return response;
|
||||||
};
|
};
|
||||||
var error = function(response) {
|
|
||||||
|
f.responseError = function(response) {
|
||||||
var status = response.status;
|
var status = response.status;
|
||||||
if (status == 401) {
|
if (status == 401) {
|
||||||
$injector.get('$state').transitionTo('welcome');
|
$injector.get('$state').transitionTo('welcome');
|
||||||
}
|
}
|
||||||
return $q.reject(response);
|
return $q.reject(response);
|
||||||
};
|
};
|
||||||
|
return f;
|
||||||
var promise = function(promise) {
|
|
||||||
return promise.then(success, error);
|
|
||||||
};
|
|
||||||
|
|
||||||
return promise;
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
$httpProvider.responseInterceptors.push(interceptor);
|
$httpProvider.interceptors.push(interceptor);
|
||||||
|
|
||||||
$stateProvider.state('feeds', {
|
$stateProvider.state('feeds', {
|
||||||
'abstract' : true,
|
'abstract' : true,
|
||||||
|
|||||||
@@ -56,13 +56,13 @@ module.factory('SettingsService', ['$resource', '$translate', function($resource
|
|||||||
res.get(function(data) {
|
res.get(function(data) {
|
||||||
s.settings = data;
|
s.settings = data;
|
||||||
var lang = s.settings.language || 'en';
|
var lang = s.settings.language || 'en';
|
||||||
|
$translate.use(lang);
|
||||||
if (lang === 'zh') {
|
if (lang === 'zh') {
|
||||||
lang = 'zh-cn';
|
lang = 'zh-cn';
|
||||||
} else if (lang === 'ms') {
|
} else if (lang === 'ms') {
|
||||||
lang = 'ms-my';
|
lang = 'ms-my';
|
||||||
}
|
}
|
||||||
moment.lang(lang, {});
|
moment.locale(lang, {});
|
||||||
$translate.use(lang);
|
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback(data);
|
callback(data);
|
||||||
}
|
}
|
||||||
@@ -182,7 +182,7 @@ module.factory('CategoryService', ['$resource', '$http', function($resource, $ht
|
|||||||
var actions = {
|
var actions = {
|
||||||
get : {
|
get : {
|
||||||
method : 'GET',
|
method : 'GET',
|
||||||
ignoreLoadingBar: true,
|
ignoreLoadingBar : true,
|
||||||
params : {
|
params : {
|
||||||
_method : 'get'
|
_method : 'get'
|
||||||
}
|
}
|
||||||
@@ -243,11 +243,14 @@ module.factory('CategoryService', ['$resource', '$http', function($resource, $ht
|
|||||||
callback(data);
|
callback(data);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
res.refresh = function(callback) {
|
res.refresh = function(success, error) {
|
||||||
res.get(function(data) {
|
res.get(function(data) {
|
||||||
_.merge(res.subscriptions, data);
|
_.merge(res.subscriptions, data);
|
||||||
if (callback)
|
if (success)
|
||||||
callback(data);
|
success(data);
|
||||||
|
}, function(data) {
|
||||||
|
if (error)
|
||||||
|
error(data);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -265,7 +268,7 @@ module.factory('EntryService', ['$resource', '$http', function($resource, $http)
|
|||||||
},
|
},
|
||||||
mark : {
|
mark : {
|
||||||
method : 'POST',
|
method : 'POST',
|
||||||
ignoreLoadingBar: true,
|
ignoreLoadingBar : true,
|
||||||
params : {
|
params : {
|
||||||
_method : 'mark'
|
_method : 'mark'
|
||||||
}
|
}
|
||||||
@@ -295,6 +298,7 @@ module.factory('EntryService', ['$resource', '$http', function($resource, $http)
|
|||||||
$http.get('rest/entry/tags').success(function(data) {
|
$http.get('rest/entry/tags').success(function(data) {
|
||||||
res.tags = [];
|
res.tags = [];
|
||||||
res.tags.push.apply(res.tags, data);
|
res.tags.push.apply(res.tags, data);
|
||||||
|
res.tags.sort();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
var oldTag = res.tag;
|
var oldTag = res.tag;
|
||||||
|
|||||||
31
src/main/app/manifest.json
Normal file
31
src/main/app/manifest.json
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"name": "CommaFeed",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "app-icon-72.png",
|
||||||
|
"sizes": "72x72",
|
||||||
|
"type": "image/png",
|
||||||
|
"density": "1.5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "app-icon-114.png",
|
||||||
|
"sizes": "96x96",
|
||||||
|
"type": "image/png",
|
||||||
|
"density": "2.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "app-icon-144.png",
|
||||||
|
"sizes": "144x144",
|
||||||
|
"type": "image/png",
|
||||||
|
"density": "3.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "app-icon-192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png",
|
||||||
|
"density": "4.0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"start_url": "/",
|
||||||
|
"display": "standalone"
|
||||||
|
}
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
@import "themes/bootstrap";
|
@import "themes/bootstrap";
|
||||||
@import "themes/ebraminio";
|
@import "themes/ebraminio";
|
||||||
@import "themes/MRACHINI";
|
@import "themes/MRACHINI";
|
||||||
|
@import "themes/nightsky";
|
||||||
@import "themes/svetla";
|
@import "themes/svetla";
|
||||||
@import "themes/dark";
|
@import "themes/dark";
|
||||||
@import "themes/third";
|
@import "themes/third";
|
||||||
|
|||||||
@@ -101,6 +101,14 @@
|
|||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.css-treeview .unread ~ .unread-counter::before {
|
||||||
|
content: '(';
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview .unread ~ .unread-counter::after {
|
||||||
|
content: ')';
|
||||||
|
}
|
||||||
|
|
||||||
.css-treeview a {
|
.css-treeview a {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: black;
|
color: black;
|
||||||
|
|||||||
@@ -13,8 +13,4 @@
|
|||||||
content: "\e018";
|
content: "\e018";
|
||||||
font-family: "readabilicons";
|
font-family: "readabilicons";
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
font-size: 21px;
|
|
||||||
top: 5px;
|
|
||||||
position: relative;
|
|
||||||
line-height: 0px;
|
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,8 @@
|
|||||||
|
a:focus {
|
||||||
|
outline: none;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
.container-full {
|
.container-full {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
@@ -43,6 +48,10 @@ label {
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pre-wrap {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
.form-horizontal .control-group {
|
.form-horizontal .control-group {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
@@ -116,19 +125,23 @@ blockquote p {
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn,.btn-large,.btn-small,.btn-mini {
|
.form-group {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn, .btn-large, .btn-small, .btn-mini {
|
||||||
border-top-left-radius: 2px;
|
border-top-left-radius: 2px;
|
||||||
border-top-right-radius: 2px;
|
border-top-right-radius: 2px;
|
||||||
border-bottom-left-radius: 2px;
|
border-bottom-left-radius: 2px;
|
||||||
border-bottom-right-radius: 2px;
|
border-bottom-right-radius: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-group>.btn:first-child,.btn-group>.btn-large:first-child {
|
.btn-group>.btn:first-child, .btn-group>.btn-large:first-child {
|
||||||
border-top-left-radius: 2px;
|
border-top-left-radius: 2px;
|
||||||
border-bottom-left-radius: 2px;
|
border-bottom-left-radius: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-group>.btn:last-child,.btn-group>.btn-large:last-child,.btn-group>.dropdown-toggle
|
.btn-group>.btn:last-child, .btn-group>.btn-large:last-child, .btn-group>.dropdown-toggle
|
||||||
{
|
{
|
||||||
border-top-right-radius: 2px;
|
border-top-right-radius: 2px;
|
||||||
border-bottom-right-radius: 2px;
|
border-bottom-right-radius: 2px;
|
||||||
|
|||||||
126
src/main/app/sass/themes/_nightsky.scss
Normal file
126
src/main/app/sass/themes/_nightsky.scss
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
#theme-nightsky {
|
||||||
|
a {
|
||||||
|
color: #2A9FD6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-pills > li.active > a, .nav-pills > li.active > a:hover, .nav-pills > li.active > a:focus {
|
||||||
|
color: #FFF;
|
||||||
|
background-color: #2A9FD6;
|
||||||
|
}
|
||||||
|
|
||||||
|
body, .toolbar {
|
||||||
|
color: #C6C6C6;
|
||||||
|
background-color: #2F2F2F;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-default {
|
||||||
|
color: #C6C6C6;
|
||||||
|
background-color: #424242;
|
||||||
|
border-color: #424242;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-default:hover, .btn-default:focus, .btn-default.focus, .btn-default:active,
|
||||||
|
.btn-default.active, .open>.dropdown-toggle.btn-default {
|
||||||
|
background-color: #282828;
|
||||||
|
border-color: #232323;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview li .tree-item:hover {
|
||||||
|
background-color: #282828;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview .unread-counter {
|
||||||
|
color: #939393;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview .category-link, .css-treeview a {
|
||||||
|
color: #939393;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview a .unread, .css-treeview .category-link .unread {
|
||||||
|
color: #C6C6C6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview .selected {
|
||||||
|
color: #C00;
|
||||||
|
}
|
||||||
|
|
||||||
|
.entrylist-header {
|
||||||
|
border-bottom: 1px solid #282828;
|
||||||
|
}
|
||||||
|
|
||||||
|
#feed-accordion .entry {
|
||||||
|
border-bottom: 1px solid #282828;
|
||||||
|
}
|
||||||
|
|
||||||
|
#feed-accordion .entry-body .entry-title {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
#feed-accordion .entry-heading .entry-name {
|
||||||
|
color: #939393;
|
||||||
|
}
|
||||||
|
|
||||||
|
#feed-accordion .unread .entry-heading .entry-name {
|
||||||
|
font-weight: normal;
|
||||||
|
color: #C6C6C6;
|
||||||
|
}
|
||||||
|
|
||||||
|
#feed-accordion .unread .entry-heading {
|
||||||
|
background-color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
#feed-accordion .entry-heading {
|
||||||
|
background-color: #2F2F2F;
|
||||||
|
}
|
||||||
|
|
||||||
|
#feed-accordion .unread .entry-heading:hover {
|
||||||
|
background-color: #2F2F2F;
|
||||||
|
}
|
||||||
|
|
||||||
|
#feed-accordion .current.closed .entry-heading {
|
||||||
|
background-color: #151515;
|
||||||
|
}
|
||||||
|
|
||||||
|
#feed-accordion .entry-heading-link {
|
||||||
|
color: #C6C6C6;
|
||||||
|
}
|
||||||
|
|
||||||
|
#feed-accordion .entry-external-link {
|
||||||
|
color: #C6C6C6;
|
||||||
|
}
|
||||||
|
|
||||||
|
#feed-accordion .icon-star-empty {
|
||||||
|
color: #C6C6C6;
|
||||||
|
}
|
||||||
|
|
||||||
|
#feed-accordion .entry-heading .feed-name {
|
||||||
|
color: #939393;
|
||||||
|
}
|
||||||
|
|
||||||
|
#feed-accordion .entry-body-content {
|
||||||
|
color: #C6C6C6;
|
||||||
|
}
|
||||||
|
|
||||||
|
#feed-accordion .entry-buttons {
|
||||||
|
background-color: #494949;
|
||||||
|
border-top: 1px solid #282828;
|
||||||
|
}
|
||||||
|
|
||||||
|
#feed-accordion .share-buttons a {
|
||||||
|
color: #C6C6C6;
|
||||||
|
}
|
||||||
|
|
||||||
|
#feed-accordion a.mark-up-to {
|
||||||
|
color: #C6C6C6;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loading-bar .bar {
|
||||||
|
background: #C6C6C6;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loading-bar .peg {
|
||||||
|
box-shadow: 0 0 10px #C6C6C6, 0 0 5px #C6C6C6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -12,8 +12,8 @@
|
|||||||
<i ng-class="{'icon-star' : node.id == 'starred', 'icon-inbox': node.id == 'all', 'icon-tag' : node.isTag}" ng-show="!showChildren"></i>
|
<i ng-class="{'icon-star' : node.id == 'starred', 'icon-inbox': node.id == 'all', 'icon-tag' : node.isTag}" ng-show="!showChildren"></i>
|
||||||
</span>
|
</span>
|
||||||
<span ng-class="{selected: (node.id == selectedId && (node.isTag ? selectedType == 'tag' : selectedType == 'category'))}">
|
<span ng-class="{selected: (node.id == selectedId && (node.isTag ? selectedType == 'tag' : selectedType == 'category'))}">
|
||||||
<span ng-class="{unread: unreadCount({category:node})}" class="bidi-embed"> {{categoryLabel(node)}} </span>
|
<span ng-class="{unread: unreadCount({category:node})}" class="bidi-embed">{{categoryLabel(node)}}</span>
|
||||||
<span class="unread-counter"> {{categoryCountLabel(node)}} </span>
|
<span class="unread-counter">{{categoryCountLabel(node)}}</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -30,8 +30,8 @@
|
|||||||
<a ng-click="feedClicked(feed.id, $event)" ng-dblclick="showFeedDetails(feed)" class="feed-link" href="{{feed.feedLink}}" target="_blank"
|
<a ng-click="feedClicked(feed.id, $event)" ng-dblclick="showFeedDetails(feed)" class="feed-link" href="{{feed.feedLink}}" target="_blank"
|
||||||
ng-class="{error: feed.message && feed.errorCount > 10, selected: (feed.id == selectedId && selectedType == 'feed') }">
|
ng-class="{error: feed.message && feed.errorCount > 10, selected: (feed.id == selectedId && selectedType == 'feed') }">
|
||||||
<favicon url="feed.iconUrl" />
|
<favicon url="feed.iconUrl" />
|
||||||
<span ng-class="{unread: feed.unread}" class="bidi-embed"> {{feed.name}} </span>
|
<span ng-class="{unread: feed.unread}" class="bidi-embed">{{feed.name}}</span>
|
||||||
<span class="unread-counter"> {{feedCountLabel(feed)}} </span>
|
<span class="unread-counter">{{feedCountLabel(feed)}}</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<button type="button" class="close" ng-click="close()">×</button>
|
<button type="button" class="close" ng-click="close()">×</button>
|
||||||
<h4>
|
<h4>
|
||||||
<input ng-model="filter" class="filter-input"
|
<input ng-model="filter" class="filter-input"
|
||||||
ui-keydown="{'up': 'focusPrevious($event)', 'down': 'focusNext($event)', 'enter': 'openFocused()' }" placeholder="'feedsearch.hint' | translate"
|
ui-keydown="{'up': 'focusPrevious($event)', 'down': 'focusNext($event)', 'enter': 'openFocused()' }" placeholder="{{'feedsearch.hint' | translate}}"
|
||||||
focus="feedSearchModal">
|
focus="feedSearchModal">
|
||||||
</h4>
|
</h4>
|
||||||
<small>{{ 'feedsearch.help' | translate }}</small>
|
<small>{{ 'feedsearch.help' | translate }}</small>
|
||||||
|
|||||||
@@ -4,14 +4,8 @@
|
|||||||
<dt>Mean</dt>
|
<dt>Mean</dt>
|
||||||
<dd>{{metric.meanRate | number:2}}</dd>
|
<dd>{{metric.meanRate | number:2}}</dd>
|
||||||
|
|
||||||
<dt>1 min</dt>
|
<dt>1/5/15 min</dt>
|
||||||
<dd>{{metric.oneMinuteRate | number:2}}</dd>
|
<dd>{{metric.oneMinuteRate | number:2}} {{metric.fiveMinuteRate | number:2}} {{metric.fifteenMinuteRate | number:2}}</dd>
|
||||||
|
|
||||||
<dt>5 min</dt>
|
|
||||||
<dd>{{metric.fiveMinuteRate | number:2}}</dd>
|
|
||||||
|
|
||||||
<dt>15 min</dt>
|
|
||||||
<dd>{{metric.fifteenMinuteRate | number:2}}</dd>
|
|
||||||
|
|
||||||
<dt>Total</dt>
|
<dt>Total</dt>
|
||||||
<dd>{{metric.count}}</dd>
|
<dd>{{metric.count}}</dd>
|
||||||
|
|||||||
17
src/main/app/templates/_metrics.timer.html
Normal file
17
src/main/app/templates/_metrics.timer.html
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<div>
|
||||||
|
<span>{{label}}</span>
|
||||||
|
<dl class="dl-horizontal">
|
||||||
|
<dt>Mean</dt>
|
||||||
|
<dd>{{metric.meanRate | number:2}}</dd>
|
||||||
|
|
||||||
|
<dt>1/5/15 min</dt>
|
||||||
|
<dd>{{metric.oneMinuteRate | number:2}} {{metric.fiveMinuteRate | number:2}} {{metric.fifteenMinuteRate | number:2}}</dd>
|
||||||
|
|
||||||
|
<dt>Total</dt>
|
||||||
|
<dd>{{metric.count}}</dd>
|
||||||
|
|
||||||
|
<dt>min/max/mean (ms)</dt>
|
||||||
|
<dd>{{metric.snapshot.min/1000000 | number:0}} {{metric.snapshot.max/1000000 | number:0}} {{metric.snapshot.mean/1000000 | number:0}}</dd>
|
||||||
|
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
<span>
|
<span>
|
||||||
<a ng-click="edit_mode=!edit_mode" class="nolink pointer">
|
<span ng-click="edit_mode=!edit_mode" class="nolink pointer">
|
||||||
<i class="icon-tags"></i>
|
<i class="icon-tags"></i>
|
||||||
{{ 'global.tags' | translate }}
|
{{ 'global.tags' | translate }}
|
||||||
</a>
|
</span>
|
||||||
<span ng-if="!edit_mode">
|
<span ng-if="!edit_mode">
|
||||||
<span class="label label-info" ng-repeat="tag in entry.tags">{{tag}}</span>
|
<span class="label label-info" ng-repeat="tag in entry.tags">{{tag}}</span>
|
||||||
</span>
|
</span>
|
||||||
<span ng-if="edit_mode">
|
<span ng-if="edit_mode">
|
||||||
<input type="text" ui-select2="select2Options" ng-model="entry.tags" class="tag-input" autofocus />
|
<input type="hidden" ui-select2="select2Options" ng-model="entry.tags" class="tag-input" autofocus />
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
@@ -6,14 +6,14 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="btn-group">
|
<div class="btn-group" id="toolbar-nav">
|
||||||
<a type="button" class="btn btn-default" ng-click="previousEntry()" title="{{ 'toolbar.previous_entry' | translate }}">
|
<a type="button" class="btn btn-default" ng-click="previousEntry()" title="{{ 'toolbar.previous_entry' | translate }}">
|
||||||
<i class="icon-chevron-up"></i>
|
<i class="icon-chevron-up"></i>
|
||||||
</a>
|
</a>
|
||||||
<a type="button" class="btn btn-default" ng-click="nextEntry()" title="{{ 'toolbar.next_entry' | translate }}">
|
<a type="button" class="btn btn-default" ng-click="nextEntry()" title="{{ 'toolbar.next_entry' | translate }}">
|
||||||
<i class="icon-chevron-down"></i>
|
<i class="icon-chevron-down"></i>
|
||||||
</a>
|
</a>
|
||||||
<div class="btn-group">
|
<div class="btn-group" id="toolbar-refresh">
|
||||||
<a type="button" class="btn btn-default" ng-click="refresh()" title="{{ 'toolbar.refresh' | translate }}">
|
<a type="button" class="btn btn-default" ng-click="refresh()" title="{{ 'toolbar.refresh' | translate }}">
|
||||||
<i class="icon-refresh"></i>
|
<i class="icon-refresh"></i>
|
||||||
</a>
|
</a>
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="btn-group">
|
<div class="btn-group" id="toolbar-mark-read">
|
||||||
<a type="button" class="btn btn-default" ng-click="markAllAsRead()" title="{{ 'toolbar.mark_all_as_read' | translate }}">
|
<a type="button" class="btn btn-default" ng-click="markAllAsRead()" title="{{ 'toolbar.mark_all_as_read' | translate }}">
|
||||||
<i class="icon-ok"></i>
|
<i class="icon-ok"></i>
|
||||||
</a>
|
</a>
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="actions btn-group">
|
<div class="actions btn-group" id="toolbar-read-mode">
|
||||||
<div ng-if="!MobileService.mobile || MobileService.rightMenu">
|
<div ng-if="!MobileService.mobile || MobileService.rightMenu">
|
||||||
<div class="btn-group read-mode">
|
<div class="btn-group read-mode">
|
||||||
<button type="button" class="btn btn-default" ng-click="settingsService.settings.readingMode = 'unread'"
|
<button type="button" class="btn btn-default" ng-click="settingsService.settings.readingMode = 'unread'"
|
||||||
@@ -66,14 +66,14 @@
|
|||||||
ng-class="{'active': settingsService.settings.readingMode == 'all'}">{{ 'toolbar.all' | translate }}</button>
|
ng-class="{'active': settingsService.settings.readingMode == 'all'}">{{ 'toolbar.all' | translate }}</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="btn-group">
|
<div class="btn-group" id="toolbar-read-order">
|
||||||
<a type="button" class="btn btn-default" ng-click="toggleOrder()" title="{{ 'toolbar.sort_by_asc_desc' | translate }}">
|
<a type="button" class="btn btn-default" ng-click="toggleOrder()" title="{{ 'toolbar.sort_by_asc_desc' | translate }}">
|
||||||
<i
|
<i
|
||||||
ng-class="{'icon-arrow-up' : settingsService.settings.readingOrder == 'asc', 'icon-arrow-down': settingsService.settings.readingOrder == 'desc'}"></i>
|
ng-class="{'icon-arrow-up' : settingsService.settings.readingOrder == 'asc', 'icon-arrow-down': settingsService.settings.readingOrder == 'desc'}"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="btn-group">
|
<div class="btn-group" id="toolbar-read-view-settings">
|
||||||
<a type="button" class="btn btn-default" ng-click="settingsService.settings.viewMode = 'title'"
|
<a type="button" class="btn btn-default" ng-click="settingsService.settings.viewMode = 'title'"
|
||||||
ng-class="{'active': settingsService.settings.viewMode == 'title'}" title="{{ 'toolbar.titles_only' | translate }}">
|
ng-class="{'active': settingsService.settings.viewMode == 'title'}" title="{{ 'toolbar.titles_only' | translate }}">
|
||||||
<i class="icon-list"></i>
|
<i class="icon-list"></i>
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="btn-group">
|
<div class="btn-group" id="toolbar-settings">
|
||||||
<a class="btn btn-default" ng-click="toSettings()" title="{{ 'toolbar.settings' | translate }}">
|
<a class="btn btn-default" ng-click="toSettings()" title="{{ 'toolbar.settings' | translate }}">
|
||||||
<i class="icon-cog"></i>
|
<i class="icon-cog"></i>
|
||||||
</a>
|
</a>
|
||||||
@@ -124,13 +124,13 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-group donate">
|
<div class="btn-group donate">
|
||||||
<a class="btn btn-success" type="button" ng-click="toHelp()" title="{{ 'toolbar.about' | translate }} / {{ 'toolbar.donate' | translate }}">
|
<button class="btn btn-success" type="button" ng-click="toHelp()" title="{{ 'toolbar.about' | translate }} / {{ 'toolbar.donate' | translate }}">
|
||||||
<i class="icon-info-sign"></i>
|
<i class="icon-info-sign"></i>
|
||||||
</a>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span ng-if="!MobileService.mobile" ng-bind-html="ServerService.announcement | trustHtml"></span>
|
<span ng-if="!MobileService.mobile" ng-bind-html="ServerService.announcement | trustHtml"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,21 +1,28 @@
|
|||||||
<div>
|
<div>
|
||||||
<metric-meter metric="metrics.meters['com.commafeed.backend.feed.FeedQueues.refill']" label="'Refresh queue refill rate (/sec)'"></metric-meter>
|
<div class="col-md-6">
|
||||||
<metric-meter metric="metrics.meters['com.commafeed.backend.feed.FeedRefreshTaskGiver.feedRefreshed']" label="'Feed refreshed (/sec)'"></metric-meter>
|
<metric-meter metric="metrics.meters['com.commafeed.backend.feed.FeedQueues.refill']" label="'Refresh queue refill rate (/sec)'"></metric-meter>
|
||||||
<metric-meter metric="metrics.meters['com.commafeed.backend.feed.FeedRefreshUpdater.feedUpdated']" label="'Feed updated (/sec)'"></metric-meter>
|
<metric-meter metric="metrics.meters['com.commafeed.backend.feed.FeedRefreshTaskGiver.feedRefreshed']" label="'Feed refreshed (/sec)'"></metric-meter>
|
||||||
<metric-meter metric="metrics.meters['com.commafeed.backend.feed.FeedRefreshUpdater.entryCacheHit']" label="'Entry cache hit (/sec)'"></metric-meter>
|
<metric-meter metric="metrics.meters['com.commafeed.backend.feed.FeedRefreshUpdater.feedUpdated']" label="'Feed updated (/sec)'"></metric-meter>
|
||||||
<metric-meter metric="metrics.meters['com.commafeed.backend.feed.FeedRefreshUpdater.entryCacheMiss']" label="'Entry cache miss (/sec)'"></metric-meter>
|
<metric-meter metric="metrics.meters['com.commafeed.backend.feed.FeedRefreshUpdater.entryCacheHit']" label="'Entry cache hit (/sec)'"></metric-meter>
|
||||||
|
<metric-meter metric="metrics.meters['com.commafeed.backend.feed.FeedRefreshUpdater.entryCacheMiss']" label="'Entry cache miss (/sec)'"></metric-meter>
|
||||||
|
|
||||||
|
<metric-gauge metric="metrics.gauges['com.commafeed.backend.feed.FeedRefreshExecutor.feed-refresh-updater.active']"
|
||||||
|
label="'Feed Updater active'"></metric-gauge>
|
||||||
|
<metric-gauge metric="metrics.gauges['com.commafeed.backend.feed.FeedRefreshExecutor.feed-refresh-updater.pending']"
|
||||||
|
label="'Feed Updater queued'"></metric-gauge>
|
||||||
|
|
||||||
<metric-gauge metric="metrics.gauges['com.commafeed.backend.feed.FeedRefreshExecutor.feed-refresh-updater.active']"
|
<metric-gauge metric="metrics.gauges['com.commafeed.backend.feed.FeedRefreshExecutor.feed-refresh-worker.active']"
|
||||||
label="'Feed Updater active'"></metric-gauge>
|
label="'Feed Worker active'"></metric-gauge>
|
||||||
<metric-gauge metric="metrics.gauges['com.commafeed.backend.feed.FeedRefreshExecutor.feed-refresh-updater.pending']"
|
<metric-gauge metric="metrics.gauges['com.commafeed.backend.feed.FeedRefreshExecutor.feed-refresh-worker.pending']"
|
||||||
label="'Feed Updater queued'"></metric-gauge>
|
label="'Feed Worker queued'"></metric-gauge>
|
||||||
|
|
||||||
<metric-gauge metric="metrics.gauges['com.commafeed.backend.feed.FeedRefreshExecutor.feed-refresh-worker.active']"
|
<metric-gauge metric="metrics.gauges['com.commafeed.backend.feed.FeedQueues.addQueue']" label="'Task Giver Add Queue'"></metric-gauge>
|
||||||
label="'Feed Worker active'"></metric-gauge>
|
<metric-gauge metric="metrics.gauges['com.commafeed.backend.feed.FeedQueues.takeQueue']" label="'Task Giver Take Queue'"></metric-gauge>
|
||||||
<metric-gauge metric="metrics.gauges['com.commafeed.backend.feed.FeedRefreshExecutor.feed-refresh-worker.pending']"
|
<metric-gauge metric="metrics.gauges['com.commafeed.backend.feed.FeedQueues.giveBackQueue']" label="'Task Giver Give Back Queue'"></metric-gauge>
|
||||||
label="'Feed Worker queued'"></metric-gauge>
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
<metric-gauge metric="metrics.gauges['com.commafeed.backend.feed.FeedQueues.addQueue']" label="'Task Giver Add Queue'"></metric-gauge>
|
<div ng-repeat="(name, timer) in metrics.timers">
|
||||||
<metric-gauge metric="metrics.gauges['com.commafeed.backend.feed.FeedQueues.takeQueue']" label="'Task Giver Take Queue'"></metric-gauge>
|
<metric-timer metric="timer" label="name"></metric-gauge>
|
||||||
<metric-gauge metric="metrics.gauges['com.commafeed.backend.feed.FeedQueues.giveBackQueue']" label="'Task Giver Give Back Queue'"></metric-gauge>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1,10 +1,14 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h1>
|
<h1>
|
||||||
Application settings
|
Application settings -
|
||||||
<small>
|
<small>
|
||||||
<a ng-click="toUsers()" class="pointer">Manage users</a>
|
<a ng-click="toUsers()" class="pointer">Manage users</a>
|
||||||
</small>
|
</small>
|
||||||
|
-
|
||||||
|
<small>
|
||||||
|
<a ng-click="toMetrics()" class="pointer">Metrics</a>
|
||||||
|
</small>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -28,26 +32,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
|
||||||
<label class="control-label col-sm-3" for="feedbackButton">Feedback button</label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<div class="checkbox">
|
|
||||||
<input type="checkbox" id="feedbackButton" name="feedbackButton" ng-model="settings.feedbackButton" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="control-label col-sm-3" for="googleClientId">Google client ID</label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input type="text" name="googleClientId" class="form-control" ng-model="settings.googleClientId" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="control-label col-sm-3" for="googleClientSecret">Google client secret</label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input type="text" name="googleClientSecret" class="form-control" ng-model="settings.googleClientSecret" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="control-label col-sm-3" for="googleAnalyticsTrackingCode">Google Analytics tracking code</label>
|
<label class="control-label col-sm-3" for="googleAnalyticsTrackingCode">Google Analytics tracking code</label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
@@ -134,14 +118,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
|
||||||
<label class="control-label col-sm-3" for="logLevel">Logging level</label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<select name="logLevel" ng-model="settings.logLevel" class="form-control"
|
|
||||||
ng-options="level for level in ['DEBUG', 'INFO', 'WARN', 'ERROR']">
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="control-label col-sm-3" for="logLevel">Database query timeout (ms)</label>
|
<label class="control-label col-sm-3" for="logLevel">Database query timeout (ms)</label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
@@ -173,8 +149,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="text-center form-group">
|
<div class="text-center form-group">
|
||||||
<button type="submit" class="btn btn-primary">Save</button>
|
<button type="button" class="btn btn-default" ng-click="cancel()">Back</button>
|
||||||
<button type="button" class="btn btn-default" ng-click="cancel()">Cancel</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-2 control-label">{{ 'details.feed_url' | translate }}</label>
|
<label class="col-sm-2 control-label">{{ 'details.feed_url' | translate }}</label>
|
||||||
<div class="col-sm-10 checkbox">
|
<div class="col-sm-10 form-control-static">
|
||||||
<a ng-show="user.apiKey" href="{{'rest/category/entriesAsFeed?id=' + category.id + '&apiKey=' + user.apiKey}}" target="_blank">{{ 'global.link' | translate }}</a>
|
<a ng-show="user.apiKey" href="{{'rest/category/entriesAsFeed?id=' + category.id + '&apiKey=' + user.apiKey}}" target="_blank">{{ 'global.link' | translate }}</a>
|
||||||
<span ng-show="!user.apiKey">{{ 'details.generate_api_key_first' | translate }}</span>
|
<span ng-show="!user.apiKey">{{ 'details.generate_api_key_first' | translate }}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
<div class="col-sm-offset-2 col-sm-10">
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
<button type="submit" class="btn btn-primary" ng-if="!isMeta()">{{ 'global.save' | translate }}</button>
|
<button type="submit" class="btn btn-primary" ng-if="!isMeta()">{{ 'global.save' | translate }}</button>
|
||||||
<button type="button" class="btn btn-danger" ng-click="deleteCategory()" ng-show="!isMeta()"
|
<button type="button" class="btn btn-danger" ng-click="deleteCategory()" ng-show="!isMeta()"
|
||||||
confirm-click="{{ 'details.delete_category_confirmation}">{{ 'global.delete' | translate }}</button>
|
confirm-click="'details.delete_category_confirmation' | translate">{{ 'global.delete' | translate }}</button>
|
||||||
<button type="button" class="btn btn-default" ng-click="back()">{{ 'global.cancel' | translate }}</button>
|
<button type="button" class="btn btn-default" ng-click="back()">{{ 'global.cancel' | translate }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,15 +3,16 @@
|
|||||||
<h3>{{ 'details.feed_details' | translate }}</h3>
|
<h3>{{ 'details.feed_details' | translate }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<form name="form" class="form-horizontal" ng-submit="save()">
|
<form name="form" class="form-horizontal" ng-submit="save()">
|
||||||
|
<div class="alert alert-danger" ng-if="error">{{ error }}</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-2 control-label">{{ 'details.url' | translate }}</label>
|
<label class="col-sm-2 control-label">{{ 'details.url' | translate }}</label>
|
||||||
<div class="col-sm-10 checkbox">
|
<div class="col-sm-10 form-control-static">
|
||||||
<a href="{{sub.feedUrl}}" target="_blank">{{sub.feedUrl}}</a>
|
<a href="{{sub.feedUrl}}" target="_blank">{{sub.feedUrl}}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-2 control-label">{{ 'details.website' | translate }}</label>
|
<label class="col-sm-2 control-label">{{ 'details.website' | translate }}</label>
|
||||||
<div class="col-sm-10 checkbox">
|
<div class="col-sm-10 form-control-static">
|
||||||
<a href="{{sub.feedLink}}" target="_blank">{{sub.feedLink}}</a>
|
<a href="{{sub.feedLink}}" target="_blank">{{sub.feedLink}}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -49,26 +50,34 @@
|
|||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-2 control-label">{{ 'details.next_refresh' | translate }}</label>
|
<label class="col-sm-2 control-label">{{ 'details.next_refresh' | translate }}</label>
|
||||||
<div class="col-sm-10 checkbox">
|
<div class="col-sm-10 form-control-static">
|
||||||
<span>{{sub.nextRefresh|entryDate:('details.queued_for_refresh' | translate) }}</span>
|
<span>{{sub.nextRefresh|entryDate:('details.queued_for_refresh' | translate) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-2 control-label">{{ 'details.message' | translate }}</label>
|
<label class="col-sm-2 control-label">{{ 'details.message' | translate }}</label>
|
||||||
<div class="col-sm-10 checkbox">
|
<div class="col-sm-10 form-control-static">
|
||||||
<span>{{sub.message}}</span>
|
<span>{{sub.message}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-2 control-label">{{ 'details.feed_url' | translate }}</label>
|
<label class="col-sm-2 control-label">{{ 'details.feed_url' | translate }}</label>
|
||||||
<div class="col-sm-10 checkbox">
|
<div class="col-sm-10 form-control-static">
|
||||||
<a ng-show="user.apiKey" href="{{'rest/feed/entriesAsFeed?id=' + sub.id + '&apiKey=' + user.apiKey}}" target="_blank">{{ 'global.link' | translate }}</a>
|
<a ng-show="user.apiKey" href="{{'rest/feed/entriesAsFeed?id=' + sub.id + '&apiKey=' + user.apiKey}}" target="_blank">{{ 'global.link' | translate }}</a>
|
||||||
<span ng-show="!user.apiKey">{{ 'details.generate_api_key_first' | translate }}</span>
|
<span ng-show="!user.apiKey">{{ 'details.generate_api_key_first' | translate }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label">{{ 'details.filtering_expression' | translate }}</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input type="text" name="filter" ng-model="sub.filter" class="form-control"></input>
|
||||||
|
<p class="help-block pre-wrap" ng-bind-html="'details.filtering_expression_help' | translate"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-sm-offset-2 col-sm-10">
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
<button type="submit" class="btn btn-primary">{{ 'global.save' | translate }}</button>
|
<button type="submit" class="btn btn-primary">{{ 'global.save' | translate }}</button>
|
||||||
|
|||||||
@@ -107,7 +107,7 @@
|
|||||||
</h4>
|
</h4>
|
||||||
<p>{{ 'about.rest_api.line1' | translate }}</p>
|
<p>{{ 'about.rest_api.line1' | translate }}</p>
|
||||||
<p>
|
<p>
|
||||||
<a href="api" target="_blank">{{ 'about.rest_api.link_to_documentation' | translate }}</a>
|
<a href="api/" target="_blank">{{ 'about.rest_api.link_to_documentation' | translate }}</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
<div infinite-scroll="loadMoreEntries()" infinite-scroll-disabled="busy || !settingsService.settings.readingMode"
|
<div infinite-scroll="loadMoreEntries()" infinite-scroll-disabled="busy || !settingsService.settings.readingMode"
|
||||||
infinite-scroll-distance="1" id="feed-accordion" ng-class="{'expanded' : settingsService.settings.viewMode == 'expanded' }">
|
infinite-scroll-distance="1" id="feed-accordion" ng-class="{'expanded' : settingsService.settings.viewMode == 'expanded' }">
|
||||||
<div ng-show="message && errorCount > 10">{{ 'view.error_while_loading_feed} : {{message}' | translate }}</div>
|
<div ng-show="message && errorCount > 10">{{ 'view.error_while_loading_feed' | translate }} : {{ message }}</div>
|
||||||
<div ng-repeat="entry in entries" class="entry entry-font-size-{{font_size}}" id="entry_{{entry.id}}"
|
<div ng-repeat="entry in entries" class="entry entry-font-size-{{font_size}}" id="entry_{{entry.id}}"
|
||||||
ng-class="{unread: entry.read == false, current: current==entry, open: isOpen, closed: !isOpen }">
|
ng-class="{unread: entry.read == false, current: current==entry, open: isOpen, closed: !isOpen }">
|
||||||
<div class="entry-heading" ng-swipe-right="mark(entry, !entry.read)">
|
<div class="entry-heading" ng-swipe-right="mark(entry, !entry.read)">
|
||||||
@@ -51,6 +51,9 @@
|
|||||||
<span class="entry-author-prefix">{{ 'view.entry_author' | translate }}</span>
|
<span class="entry-author-prefix">{{ 'view.entry_author' | translate }}</span>
|
||||||
<span class="entry-author-name">{{entry.author}}</span>
|
<span class="entry-author-name">{{entry.author}}</span>
|
||||||
</span>
|
</span>
|
||||||
|
<span class="entry-categories" ng-if="entry.categories">
|
||||||
|
<span class="entry-categories-name">({{entry.categories}})</span>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -58,8 +61,7 @@
|
|||||||
<div class="entry-body-content">
|
<div class="entry-body-content">
|
||||||
<div ng-if="!MobileService.mobile" ng-bind-html="entry.content | iframeHttpsRewrite| highlight:keywords | trustHtml"></div>
|
<div ng-if="!MobileService.mobile" ng-bind-html="entry.content | iframeHttpsRewrite| highlight:keywords | trustHtml"></div>
|
||||||
<div ng-if="MobileService.mobile" ng-bind-html="entry.content | iframeHttpsRewrite| highlight:keywords | appendImageTitles | trustHtml"></div>
|
<div ng-if="MobileService.mobile" ng-bind-html="entry.content | iframeHttpsRewrite| highlight:keywords | appendImageTitles | trustHtml"></div>
|
||||||
|
<div class="entry-enclosure" ng-if="entry.enclosureType && (entry.enclosureUrl && entry.content && entry.content.indexOf(entry.enclosureUrl) == -1)">
|
||||||
<div class="entry-enclosure" ng-if="entry.enclosureType">
|
|
||||||
<video controls ng-if="entry.enclosureType && entry.enclosureType.indexOf('video') == 0">
|
<video controls ng-if="entry.enclosureType && entry.enclosureType.indexOf('video') == 0">
|
||||||
<source ng-src="{{entry.enclosureUrl | trustUrl}}" type="{{entry.enclosureType}}" />
|
<source ng-src="{{entry.enclosureUrl | trustUrl}}" type="{{entry.enclosureType}}" />
|
||||||
</video>
|
</video>
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-2 control-label" for="email">{{ 'profile.email' | translate }}</label>
|
<label class="col-sm-2 control-label" for="email">{{ 'profile.email' | translate }}</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<input type="email" id="email" ng-model="user.email" class="form-control" />
|
<input type="email" id="email" ng-model="user.email" class="form-control" autocomplete="off" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-2 control-label" for="password">{{ 'profile.change_password' | translate }}</label>
|
<label class="col-sm-2 control-label" for="password">{{ 'profile.change_password' | translate }}</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<input type="password" name="password" id="password" ng-model="user.password" class="form-control" ng-minlength="6" />
|
<input type="password" name="password" id="password" ng-model="user.password" class="form-control" ng-minlength="6" autocomplete="off" />
|
||||||
<span class="help-inline" ng-show="profileForm.password.$error.minlength">{{ 'profile.minimum_6_chars' | translate }}</span>
|
<span class="help-inline" ng-show="profileForm.password.$error.minlength">{{ 'profile.minimum_6_chars' | translate }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
<label class="col-sm-2 control-label" for="password">{{ 'profile.confirm_password' | translate }}</label>
|
<label class="col-sm-2 control-label" for="password">{{ 'profile.confirm_password' | translate }}</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<input type="password" class="form-control" name="password_c" id="password_c" ng-model="password_c"
|
<input type="password" class="form-control" name="password_c" id="password_c" ng-model="password_c"
|
||||||
ui-validate="'$value==user.password'" ui-validate-watch="'user.password'">
|
ui-validate="'$value==user.password'" ui-validate-watch="'user.password'" autocomplete="off">
|
||||||
<span class="help-inline" ng-show="profileForm.password_c.$error.validator">{{ 'profile.passwords_do_not_match' | translate }}</span>
|
<span class="help-inline" ng-show="profileForm.password_c.$error.validator">{{ 'profile.passwords_do_not_match' | translate }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -57,7 +57,8 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-sm-offset-2 col-sm-10">
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
<button type="submit" class="btn btn-primary">{{ 'global.save' | translate }}</button>
|
<button type="submit" class="btn btn-primary">{{ 'global.save' | translate }}</button>
|
||||||
<button type="button" class="btn btn-danger" ng-click="deleteAccount()" confirm-click="'profile.delete_account_confirmation' | translate">{{ 'profile.delete_account' | translate }}</button>
|
<button type="button" class="btn btn-danger" ng-click="deleteAccount()"
|
||||||
|
confirm-click="'profile.delete_account_confirmation' | translate">{{ 'profile.delete_account' | translate }}</button>
|
||||||
<button type="button" class="btn btn-default" ng-click="cancel()">{{ 'global.cancel' | translate }}</button>
|
<button type="button" class="btn btn-default" ng-click="cancel()">{{ 'global.cancel' | translate }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -90,7 +90,7 @@
|
|||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
- REST API
|
- REST API
|
||||||
<a href="api" target="_blank">documentation</a>
|
<a href="api/" target="_blank">documentation</a>
|
||||||
</span>
|
</span>
|
||||||
<span class="pull-right">
|
<span class="pull-right">
|
||||||
<a href="https://twitter.com/CommaFeed" class="twitter-follow-button" data-show-count="false" data-size="large">Follow @CommaFeed</a>
|
<a href="https://twitter.com/CommaFeed" class="twitter-follow-button" data-show-count="false" data-size="large">Follow @CommaFeed</a>
|
||||||
|
|||||||
@@ -1,44 +1,21 @@
|
|||||||
package com.commafeed;
|
package com.commafeed;
|
||||||
|
|
||||||
import io.dropwizard.Application;
|
import java.io.IOException;
|
||||||
import io.dropwizard.assets.AssetsBundle;
|
|
||||||
import io.dropwizard.db.DataSourceFactory;
|
|
||||||
import io.dropwizard.hibernate.HibernateBundle;
|
|
||||||
import io.dropwizard.jersey.sessions.HttpSessionProvider;
|
|
||||||
import io.dropwizard.migrations.MigrationsBundle;
|
|
||||||
import io.dropwizard.setup.Bootstrap;
|
|
||||||
import io.dropwizard.setup.Environment;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.EnumSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import javax.servlet.DispatcherType;
|
||||||
|
import javax.servlet.FilterChain;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
import javax.servlet.ServletResponse;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import org.eclipse.jetty.server.session.HashSessionManager;
|
|
||||||
import org.eclipse.jetty.server.session.SessionHandler;
|
import org.eclipse.jetty.server.session.SessionHandler;
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
|
||||||
import com.codahale.metrics.MetricRegistry;
|
|
||||||
import com.commafeed.CommaFeedConfiguration.CacheType;
|
|
||||||
import com.commafeed.backend.HttpGetter;
|
|
||||||
import com.commafeed.backend.cache.CacheService;
|
|
||||||
import com.commafeed.backend.cache.NoopCacheService;
|
|
||||||
import com.commafeed.backend.cache.RedisCacheService;
|
|
||||||
import com.commafeed.backend.dao.FeedCategoryDAO;
|
|
||||||
import com.commafeed.backend.dao.FeedDAO;
|
|
||||||
import com.commafeed.backend.dao.FeedEntryContentDAO;
|
|
||||||
import com.commafeed.backend.dao.FeedEntryDAO;
|
|
||||||
import com.commafeed.backend.dao.FeedEntryStatusDAO;
|
|
||||||
import com.commafeed.backend.dao.FeedEntryTagDAO;
|
|
||||||
import com.commafeed.backend.dao.FeedSubscriptionDAO;
|
|
||||||
import com.commafeed.backend.dao.UserDAO;
|
|
||||||
import com.commafeed.backend.dao.UserRoleDAO;
|
|
||||||
import com.commafeed.backend.dao.UserSettingsDAO;
|
|
||||||
import com.commafeed.backend.feed.FaviconFetcher;
|
|
||||||
import com.commafeed.backend.feed.FeedFetcher;
|
|
||||||
import com.commafeed.backend.feed.FeedParser;
|
|
||||||
import com.commafeed.backend.feed.FeedQueues;
|
|
||||||
import com.commafeed.backend.feed.FeedRefreshTaskGiver;
|
import com.commafeed.backend.feed.FeedRefreshTaskGiver;
|
||||||
import com.commafeed.backend.feed.FeedRefreshUpdater;
|
import com.commafeed.backend.feed.FeedRefreshUpdater;
|
||||||
import com.commafeed.backend.feed.FeedRefreshWorker;
|
import com.commafeed.backend.feed.FeedRefreshWorker;
|
||||||
@@ -53,26 +30,10 @@ import com.commafeed.backend.model.FeedSubscription;
|
|||||||
import com.commafeed.backend.model.User;
|
import com.commafeed.backend.model.User;
|
||||||
import com.commafeed.backend.model.UserRole;
|
import com.commafeed.backend.model.UserRole;
|
||||||
import com.commafeed.backend.model.UserSettings;
|
import com.commafeed.backend.model.UserSettings;
|
||||||
import com.commafeed.backend.opml.OPMLExporter;
|
|
||||||
import com.commafeed.backend.opml.OPMLImporter;
|
|
||||||
import com.commafeed.backend.service.ApplicationPropertiesService;
|
|
||||||
import com.commafeed.backend.service.DatabaseCleaningService;
|
|
||||||
import com.commafeed.backend.service.FeedEntryContentService;
|
|
||||||
import com.commafeed.backend.service.FeedEntryService;
|
|
||||||
import com.commafeed.backend.service.FeedEntryTagService;
|
|
||||||
import com.commafeed.backend.service.FeedService;
|
|
||||||
import com.commafeed.backend.service.FeedSubscriptionService;
|
|
||||||
import com.commafeed.backend.service.FeedUpdateService;
|
|
||||||
import com.commafeed.backend.service.MailService;
|
|
||||||
import com.commafeed.backend.service.PasswordEncryptionService;
|
|
||||||
import com.commafeed.backend.service.PubSubService;
|
|
||||||
import com.commafeed.backend.service.StartupService;
|
import com.commafeed.backend.service.StartupService;
|
||||||
import com.commafeed.backend.service.UserService;
|
import com.commafeed.backend.service.UserService;
|
||||||
import com.commafeed.backend.task.OldStatusesCleanupTask;
|
import com.commafeed.backend.task.ScheduledTask;
|
||||||
import com.commafeed.backend.task.OrphansCleanupTask;
|
import com.commafeed.frontend.auth.SecurityCheckFactoryProvider;
|
||||||
import com.commafeed.backend.task.SchedulingService;
|
|
||||||
import com.commafeed.frontend.auth.SecurityCheckProvider;
|
|
||||||
import com.commafeed.frontend.auth.SecurityCheckProvider.SecurityCheckUserServiceProvider;
|
|
||||||
import com.commafeed.frontend.resource.AdminREST;
|
import com.commafeed.frontend.resource.AdminREST;
|
||||||
import com.commafeed.frontend.resource.CategoryREST;
|
import com.commafeed.frontend.resource.CategoryREST;
|
||||||
import com.commafeed.frontend.resource.EntryREST;
|
import com.commafeed.frontend.resource.EntryREST;
|
||||||
@@ -84,174 +45,127 @@ import com.commafeed.frontend.servlet.AnalyticsServlet;
|
|||||||
import com.commafeed.frontend.servlet.CustomCssServlet;
|
import com.commafeed.frontend.servlet.CustomCssServlet;
|
||||||
import com.commafeed.frontend.servlet.LogoutServlet;
|
import com.commafeed.frontend.servlet.LogoutServlet;
|
||||||
import com.commafeed.frontend.servlet.NextUnreadServlet;
|
import com.commafeed.frontend.servlet.NextUnreadServlet;
|
||||||
import com.wordnik.swagger.config.ConfigFactory;
|
import com.commafeed.frontend.session.SessionHelperFactoryProvider;
|
||||||
import com.wordnik.swagger.config.ScannerFactory;
|
import com.google.inject.Guice;
|
||||||
import com.wordnik.swagger.config.SwaggerConfig;
|
import com.google.inject.Injector;
|
||||||
import com.wordnik.swagger.jaxrs.config.DefaultJaxrsScanner;
|
import com.google.inject.Key;
|
||||||
import com.wordnik.swagger.jaxrs.listing.ApiDeclarationProvider;
|
import com.google.inject.TypeLiteral;
|
||||||
import com.wordnik.swagger.jaxrs.listing.ApiListingResourceJSON;
|
|
||||||
import com.wordnik.swagger.jaxrs.listing.ResourceListingProvider;
|
import io.dropwizard.Application;
|
||||||
import com.wordnik.swagger.jaxrs.reader.DefaultJaxrsApiReader;
|
import io.dropwizard.assets.AssetsBundle;
|
||||||
import com.wordnik.swagger.reader.ClassReaders;
|
import io.dropwizard.db.DataSourceFactory;
|
||||||
|
import io.dropwizard.forms.MultiPartBundle;
|
||||||
|
import io.dropwizard.hibernate.HibernateBundle;
|
||||||
|
import io.dropwizard.migrations.MigrationsBundle;
|
||||||
|
import io.dropwizard.server.DefaultServerFactory;
|
||||||
|
import io.dropwizard.servlets.CacheBustingFilter;
|
||||||
|
import io.dropwizard.setup.Bootstrap;
|
||||||
|
import io.dropwizard.setup.Environment;
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
public class CommaFeedApplication extends Application<CommaFeedConfiguration> {
|
public class CommaFeedApplication extends Application<CommaFeedConfiguration> {
|
||||||
|
|
||||||
public static final String USERNAME_ADMIN = "admin";
|
public static final String USERNAME_ADMIN = "admin";
|
||||||
public static final String USERNAME_DEMO = "demo";
|
public static final String USERNAME_DEMO = "demo";
|
||||||
|
|
||||||
public static final String SESSION_USER = "user";
|
|
||||||
|
|
||||||
public static final Date STARTUP_TIME = new Date();
|
public static final Date STARTUP_TIME = new Date();
|
||||||
|
|
||||||
private HibernateBundle<CommaFeedConfiguration> hibernateBundle;
|
private HibernateBundle<CommaFeedConfiguration> hibernateBundle;
|
||||||
private MigrationsBundle<CommaFeedConfiguration> migrationsBundle;
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "CommaFeed";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(Bootstrap<CommaFeedConfiguration> bootstrap) {
|
public void initialize(Bootstrap<CommaFeedConfiguration> bootstrap) {
|
||||||
hibernateBundle = new HibernateBundle<CommaFeedConfiguration>(AbstractModel.class, Feed.class, FeedCategory.class, FeedEntry.class,
|
bootstrap.addBundle(hibernateBundle = new HibernateBundle<CommaFeedConfiguration>(AbstractModel.class, Feed.class,
|
||||||
FeedEntryContent.class, FeedEntryStatus.class, FeedEntryTag.class, FeedSubscription.class, User.class, UserRole.class,
|
FeedCategory.class, FeedEntry.class, FeedEntryContent.class, FeedEntryStatus.class, FeedEntryTag.class,
|
||||||
UserSettings.class) {
|
FeedSubscription.class, User.class, UserRole.class, UserSettings.class) {
|
||||||
@Override
|
@Override
|
||||||
public DataSourceFactory getDataSourceFactory(CommaFeedConfiguration configuration) {
|
public DataSourceFactory getDataSourceFactory(CommaFeedConfiguration configuration) {
|
||||||
return configuration.getDatabase();
|
DataSourceFactory factory = configuration.getDataSourceFactory();
|
||||||
}
|
|
||||||
};
|
|
||||||
bootstrap.addBundle(hibernateBundle);
|
|
||||||
|
|
||||||
migrationsBundle = new MigrationsBundle<CommaFeedConfiguration>() {
|
// keep using old id generator for backward compatibility
|
||||||
|
factory.getProperties().put(AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS, "false");
|
||||||
|
|
||||||
|
factory.getProperties().put(AvailableSettings.STATEMENT_BATCH_SIZE, "50");
|
||||||
|
factory.getProperties().put(AvailableSettings.BATCH_VERSIONED_DATA, "true");
|
||||||
|
return factory;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
bootstrap.addBundle(new MigrationsBundle<CommaFeedConfiguration>() {
|
||||||
@Override
|
@Override
|
||||||
public DataSourceFactory getDataSourceFactory(CommaFeedConfiguration configuration) {
|
public DataSourceFactory getDataSourceFactory(CommaFeedConfiguration configuration) {
|
||||||
return configuration.getDatabase();
|
return configuration.getDataSourceFactory();
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
bootstrap.addBundle(migrationsBundle);
|
|
||||||
|
|
||||||
bootstrap.addBundle(new AssetsBundle("/assets/", "/", "index.html"));
|
bootstrap.addBundle(new AssetsBundle("/assets/", "/", "index.html"));
|
||||||
|
bootstrap.addBundle(new MultiPartBundle());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(CommaFeedConfiguration config, Environment environment) throws Exception {
|
public void run(CommaFeedConfiguration config, Environment environment) throws Exception {
|
||||||
MetricRegistry metrics = environment.metrics();
|
// guice init
|
||||||
SessionFactory sessionFactory = hibernateBundle.getSessionFactory();
|
Injector injector = Guice.createInjector(new CommaFeedModule(hibernateBundle.getSessionFactory(), config, environment.metrics()));
|
||||||
|
|
||||||
CacheService cacheService = config.getApplicationSettings().getCache() == CacheType.NOOP ? new NoopCacheService()
|
// session management
|
||||||
: new RedisCacheService();
|
environment.servlets().setSessionHandler(new SessionHandler(config.getSessionManagerFactory().build()));
|
||||||
log.info("using cache {}", cacheService.getClass());
|
|
||||||
|
|
||||||
// DAOs
|
// support for "@SecurityCheck User user" injection
|
||||||
FeedCategoryDAO feedCategoryDAO = new FeedCategoryDAO(sessionFactory);
|
environment.jersey().register(new SecurityCheckFactoryProvider.Binder(injector.getInstance(UserService.class)));
|
||||||
FeedDAO feedDAO = new FeedDAO(sessionFactory);
|
// support for "@Context SessionHelper sessionHelper" injection
|
||||||
FeedEntryContentDAO feedEntryContentDAO = new FeedEntryContentDAO(sessionFactory);
|
environment.jersey().register(new SessionHelperFactoryProvider.Binder());
|
||||||
FeedEntryDAO feedEntryDAO = new FeedEntryDAO(sessionFactory);
|
|
||||||
FeedEntryTagDAO feedEntryTagDAO = new FeedEntryTagDAO(sessionFactory);
|
|
||||||
FeedSubscriptionDAO feedSubscriptionDAO = new FeedSubscriptionDAO(sessionFactory);
|
|
||||||
UserDAO userDAO = new UserDAO(sessionFactory);
|
|
||||||
UserRoleDAO userRoleDAO = new UserRoleDAO(sessionFactory);
|
|
||||||
UserSettingsDAO userSettingsDAO = new UserSettingsDAO(sessionFactory);
|
|
||||||
FeedEntryStatusDAO feedEntryStatusDAO = new FeedEntryStatusDAO(sessionFactory, feedEntryDAO, feedEntryTagDAO, config);
|
|
||||||
|
|
||||||
// Queuing system
|
|
||||||
FeedQueues queues = new FeedQueues(feedDAO, config, metrics);
|
|
||||||
|
|
||||||
// Services
|
|
||||||
ApplicationPropertiesService applicationPropertiesService = new ApplicationPropertiesService();
|
|
||||||
DatabaseCleaningService cleaningService = new DatabaseCleaningService(sessionFactory, feedDAO, feedEntryDAO, feedEntryContentDAO,
|
|
||||||
feedEntryStatusDAO);
|
|
||||||
FeedEntryContentService feedEntryContentService = new FeedEntryContentService(feedEntryContentDAO);
|
|
||||||
FeedEntryService feedEntryService = new FeedEntryService(feedSubscriptionDAO, feedEntryDAO, feedEntryStatusDAO, cacheService);
|
|
||||||
FeedEntryTagService feedEntryTagService = new FeedEntryTagService(feedEntryDAO, feedEntryTagDAO);
|
|
||||||
FeedService feedService = new FeedService(feedDAO);
|
|
||||||
FeedSubscriptionService feedSubscriptionService = new FeedSubscriptionService(feedEntryStatusDAO, feedSubscriptionDAO, feedService,
|
|
||||||
queues, cacheService, config);
|
|
||||||
FeedUpdateService feedUpdateService = new FeedUpdateService(feedEntryDAO, feedEntryContentService);
|
|
||||||
MailService mailService = new MailService(config);
|
|
||||||
PasswordEncryptionService encryptionService = new PasswordEncryptionService();
|
|
||||||
PubSubService pubSubService = new PubSubService(config, queues);
|
|
||||||
UserService userService = new UserService(feedCategoryDAO, userDAO, userSettingsDAO, feedSubscriptionService, encryptionService,
|
|
||||||
config);
|
|
||||||
StartupService startupService = new StartupService(sessionFactory, userDAO, userService);
|
|
||||||
OPMLImporter opmlImporter = new OPMLImporter(feedCategoryDAO, feedSubscriptionService, cacheService);
|
|
||||||
OPMLExporter opmlExporter = new OPMLExporter(feedCategoryDAO, feedSubscriptionDAO);
|
|
||||||
|
|
||||||
// Feed fetching/parsing
|
|
||||||
HttpGetter httpGetter = new HttpGetter();
|
|
||||||
FeedParser feedParser = new FeedParser();
|
|
||||||
FaviconFetcher faviconFetcher = new FaviconFetcher(httpGetter);
|
|
||||||
FeedFetcher feedFetcher = new FeedFetcher(feedParser, httpGetter);
|
|
||||||
FeedRefreshUpdater feedUpdater = new FeedRefreshUpdater(sessionFactory, feedUpdateService, pubSubService, queues, config, metrics,
|
|
||||||
feedSubscriptionDAO, cacheService);
|
|
||||||
FeedRefreshWorker feedWorker = new FeedRefreshWorker(feedUpdater, feedFetcher, queues, config, metrics);
|
|
||||||
FeedRefreshTaskGiver taskGiver = new FeedRefreshTaskGiver(sessionFactory, queues, feedDAO, feedWorker, config, metrics);
|
|
||||||
|
|
||||||
// Auth/session management
|
|
||||||
HashSessionManager sessionManager = new HashSessionManager();
|
|
||||||
sessionManager.setHttpOnly(true);
|
|
||||||
sessionManager.getSessionCookieConfig().setHttpOnly(true);
|
|
||||||
|
|
||||||
sessionManager.setStoreDirectory(new File("sessions"));
|
|
||||||
sessionManager.getSessionCookieConfig().setMaxAge((int) TimeUnit.DAYS.toSeconds(30));
|
|
||||||
sessionManager.setMaxInactiveInterval((int) TimeUnit.DAYS.toSeconds(30));
|
|
||||||
|
|
||||||
sessionManager.setDeleteUnrestorableSessions(true);
|
|
||||||
sessionManager.setIdleSavePeriod((int) TimeUnit.HOURS.toSeconds(2));
|
|
||||||
sessionManager.setRefreshCookieAge((int) TimeUnit.DAYS.toSeconds(1));
|
|
||||||
sessionManager.setSavePeriod((int) TimeUnit.MINUTES.toSeconds(5));
|
|
||||||
sessionManager.setScavengePeriod((int) TimeUnit.MINUTES.toSeconds(5));
|
|
||||||
|
|
||||||
environment.servlets().setSessionHandler(new SessionHandler(sessionManager));
|
|
||||||
environment.jersey().register(new SecurityCheckUserServiceProvider(userService));
|
|
||||||
environment.jersey().register(SecurityCheckProvider.class);
|
|
||||||
environment.jersey().register(HttpSessionProvider.class);
|
|
||||||
|
|
||||||
// REST resources
|
// REST resources
|
||||||
environment.jersey().setUrlPattern("/rest/*");
|
environment.jersey().setUrlPattern("/rest/*");
|
||||||
environment.jersey()
|
((DefaultServerFactory) config.getServerFactory()).setJerseyRootPath("/rest/*");
|
||||||
.register(new AdminREST(userDAO, userRoleDAO, userService, encryptionService, cleaningService, config, metrics));
|
environment.jersey().register(injector.getInstance(AdminREST.class));
|
||||||
environment.jersey().register(
|
environment.jersey().register(injector.getInstance(CategoryREST.class));
|
||||||
new CategoryREST(feedCategoryDAO, feedEntryStatusDAO, feedSubscriptionDAO, feedEntryService, feedSubscriptionService,
|
environment.jersey().register(injector.getInstance(EntryREST.class));
|
||||||
cacheService, config));
|
environment.jersey().register(injector.getInstance(FeedREST.class));
|
||||||
environment.jersey().register(new EntryREST(feedEntryTagDAO, feedEntryService, feedEntryTagService));
|
environment.jersey().register(injector.getInstance(PubSubHubbubCallbackREST.class));
|
||||||
environment.jersey().register(
|
environment.jersey().register(injector.getInstance(ServerREST.class));
|
||||||
new FeedREST(feedSubscriptionDAO, feedCategoryDAO, feedEntryStatusDAO, faviconFetcher, feedFetcher, feedEntryService,
|
environment.jersey().register(injector.getInstance(UserREST.class));
|
||||||
feedSubscriptionService, queues, opmlImporter, opmlExporter, cacheService, config));
|
|
||||||
environment.jersey().register(new PubSubHubbubCallbackREST(feedDAO, feedParser, queues, config, metrics));
|
|
||||||
environment.jersey().register(new ServerREST(httpGetter, config, applicationPropertiesService));
|
|
||||||
environment.jersey().register(
|
|
||||||
new UserREST(userDAO, userRoleDAO, userSettingsDAO, userService, encryptionService, mailService, config));
|
|
||||||
|
|
||||||
// Servlets
|
// Servlets
|
||||||
NextUnreadServlet nextUnreadServlet = new NextUnreadServlet(sessionFactory, feedSubscriptionDAO, feedEntryStatusDAO,
|
environment.servlets().addServlet("next", injector.getInstance(NextUnreadServlet.class)).addMapping("/next");
|
||||||
feedCategoryDAO, config);
|
environment.servlets().addServlet("logout", injector.getInstance(LogoutServlet.class)).addMapping("/logout");
|
||||||
LogoutServlet logoutServlet = new LogoutServlet(config);
|
environment.servlets().addServlet("customCss", injector.getInstance(CustomCssServlet.class)).addMapping("/custom_css.css");
|
||||||
CustomCssServlet customCssServlet = new CustomCssServlet(sessionFactory, userSettingsDAO);
|
environment.servlets().addServlet("analytics.js", injector.getInstance(AnalyticsServlet.class)).addMapping("/analytics.js");
|
||||||
AnalyticsServlet analyticsServlet = new AnalyticsServlet(config);
|
|
||||||
environment.servlets().addServlet("next", nextUnreadServlet).addMapping("/next");
|
|
||||||
environment.servlets().addServlet("logout", logoutServlet).addMapping("/logout");
|
|
||||||
environment.servlets().addServlet("customCss", customCssServlet).addMapping("/custom_css.css");
|
|
||||||
environment.servlets().addServlet("analytics.js", analyticsServlet).addMapping("/analytics.js");
|
|
||||||
|
|
||||||
// Tasks
|
// Scheduled tasks
|
||||||
SchedulingService schedulingService = new SchedulingService();
|
Set<ScheduledTask> tasks = injector.getInstance(Key.get(new TypeLiteral<Set<ScheduledTask>>() {
|
||||||
schedulingService.register(new OldStatusesCleanupTask(config, cleaningService));
|
}));
|
||||||
schedulingService.register(new OrphansCleanupTask(cleaningService));
|
ScheduledExecutorService executor = environment.lifecycle().scheduledExecutorService("task-scheduler", true).threads(tasks.size())
|
||||||
|
.build();
|
||||||
|
for (ScheduledTask task : tasks) {
|
||||||
|
task.register(executor);
|
||||||
|
}
|
||||||
|
|
||||||
// Managed objects
|
// database init/changelogs
|
||||||
environment.lifecycle().manage(startupService);
|
environment.lifecycle().manage(injector.getInstance(StartupService.class));
|
||||||
environment.lifecycle().manage(taskGiver);
|
|
||||||
environment.lifecycle().manage(feedWorker);
|
// background feed fetching
|
||||||
environment.lifecycle().manage(feedUpdater);
|
environment.lifecycle().manage(injector.getInstance(FeedRefreshTaskGiver.class));
|
||||||
environment.lifecycle().manage(schedulingService);
|
environment.lifecycle().manage(injector.getInstance(FeedRefreshWorker.class));
|
||||||
|
environment.lifecycle().manage(injector.getInstance(FeedRefreshUpdater.class));
|
||||||
|
|
||||||
|
// cache configuration
|
||||||
|
// prevent caching on REST resources, except for favicons
|
||||||
|
environment.servlets().addFilter("cache-filter", new CacheBustingFilter() {
|
||||||
|
@Override
|
||||||
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||||
|
String path = ((HttpServletRequest) request).getRequestURI();
|
||||||
|
if (path.contains("/feed/favicon")) {
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
} else {
|
||||||
|
super.doFilter(request, response, chain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), false, "/rest/*");
|
||||||
|
|
||||||
// Swagger
|
|
||||||
environment.jersey().register(new ApiListingResourceJSON());
|
|
||||||
environment.jersey().register(new ApiDeclarationProvider());
|
|
||||||
environment.jersey().register(new ResourceListingProvider());
|
|
||||||
ScannerFactory.setScanner(new DefaultJaxrsScanner());
|
|
||||||
ClassReaders.setReader(new DefaultJaxrsApiReader());
|
|
||||||
SwaggerConfig swaggerConfig = ConfigFactory.config();
|
|
||||||
swaggerConfig.setApiVersion("1");
|
|
||||||
swaggerConfig.setBasePath("/rest");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
|||||||
@@ -4,14 +4,19 @@ import io.dropwizard.Configuration;
|
|||||||
import io.dropwizard.db.DataSourceFactory;
|
import io.dropwizard.db.DataSourceFactory;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
import javax.validation.constraints.Min;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
import org.apache.commons.lang.time.DateUtils;
|
import org.apache.commons.lang3.time.DateUtils;
|
||||||
|
import org.hibernate.validator.constraints.NotBlank;
|
||||||
|
|
||||||
|
import com.commafeed.backend.cache.RedisPoolFactory;
|
||||||
|
import com.commafeed.frontend.session.SessionManagerFactory;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@@ -21,70 +26,114 @@ public class CommaFeedConfiguration extends Configuration {
|
|||||||
NOOP, REDIS
|
NOOP, REDIS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ResourceBundle bundle;
|
||||||
|
|
||||||
|
public CommaFeedConfiguration() {
|
||||||
|
bundle = ResourceBundle.getBundle("application");
|
||||||
|
}
|
||||||
|
|
||||||
@Valid
|
@Valid
|
||||||
@NotNull
|
@NotNull
|
||||||
@JsonProperty("database")
|
@JsonProperty("database")
|
||||||
private DataSourceFactory database = new DataSourceFactory();
|
private DataSourceFactory dataSourceFactory = new DataSourceFactory();
|
||||||
|
|
||||||
|
@Valid
|
||||||
|
@NotNull
|
||||||
|
@JsonProperty("redis")
|
||||||
|
private RedisPoolFactory redisPoolFactory = new RedisPoolFactory();
|
||||||
|
|
||||||
|
@Valid
|
||||||
|
@NotNull
|
||||||
|
@JsonProperty("session")
|
||||||
|
private SessionManagerFactory sessionManagerFactory = new SessionManagerFactory();
|
||||||
|
|
||||||
@Valid
|
@Valid
|
||||||
@NotNull
|
@NotNull
|
||||||
@JsonProperty("app")
|
@JsonProperty("app")
|
||||||
private ApplicationSettings applicationSettings;
|
private ApplicationSettings applicationSettings;
|
||||||
|
|
||||||
|
public String getVersion() {
|
||||||
|
return bundle.getString("version");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGitCommit() {
|
||||||
|
return bundle.getString("git.commit");
|
||||||
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public static class ApplicationSettings {
|
public static class ApplicationSettings {
|
||||||
@JsonProperty
|
@NotNull
|
||||||
|
@NotBlank
|
||||||
|
@Valid
|
||||||
private String publicUrl;
|
private String publicUrl;
|
||||||
|
|
||||||
@JsonProperty
|
@NotNull
|
||||||
private boolean allowRegistrations;
|
@Valid
|
||||||
|
private Boolean allowRegistrations;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Valid
|
||||||
|
private Boolean createDemoAccount;
|
||||||
|
|
||||||
@JsonProperty
|
|
||||||
private String googleAnalyticsTrackingCode;
|
private String googleAnalyticsTrackingCode;
|
||||||
|
|
||||||
@JsonProperty
|
private String googleAuthKey;
|
||||||
private int backgroundThreads;
|
|
||||||
|
|
||||||
@JsonProperty
|
@NotNull
|
||||||
private int databaseUpdateThreads;
|
@Min(1)
|
||||||
|
@Valid
|
||||||
|
private Integer backgroundThreads;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Min(1)
|
||||||
|
@Valid
|
||||||
|
private Integer databaseUpdateThreads;
|
||||||
|
|
||||||
@JsonProperty
|
|
||||||
private String smtpHost;
|
private String smtpHost;
|
||||||
|
|
||||||
@JsonProperty
|
|
||||||
private int smtpPort;
|
private int smtpPort;
|
||||||
|
|
||||||
@JsonProperty
|
|
||||||
private boolean smtpTls;
|
private boolean smtpTls;
|
||||||
|
|
||||||
@JsonProperty
|
|
||||||
private String smtpUserName;
|
private String smtpUserName;
|
||||||
|
|
||||||
@JsonProperty
|
|
||||||
private String smtpPassword;
|
private String smtpPassword;
|
||||||
|
private String smtpFromAddress;
|
||||||
|
|
||||||
@JsonProperty
|
@NotNull
|
||||||
private boolean heavyLoad;
|
@Valid
|
||||||
|
private Boolean heavyLoad;
|
||||||
|
|
||||||
@JsonProperty
|
@NotNull
|
||||||
private boolean pubsubhubbub;
|
@Valid
|
||||||
|
private Boolean pubsubhubbub;
|
||||||
|
|
||||||
@JsonProperty
|
@NotNull
|
||||||
private boolean imageProxyEnabled;
|
@Valid
|
||||||
|
private Boolean imageProxyEnabled;
|
||||||
|
|
||||||
@JsonProperty
|
@NotNull
|
||||||
private int queryTimeout;
|
@Min(0)
|
||||||
|
@Valid
|
||||||
|
private Integer queryTimeout;
|
||||||
|
|
||||||
@JsonProperty
|
@NotNull
|
||||||
private int keepStatusDays;
|
@Min(0)
|
||||||
|
@Valid
|
||||||
|
private Integer keepStatusDays;
|
||||||
|
|
||||||
@JsonProperty
|
@NotNull
|
||||||
private int refreshIntervalMinutes;
|
@Min(0)
|
||||||
|
@Valid
|
||||||
|
private Integer maxFeedCapacity;
|
||||||
|
|
||||||
@JsonProperty
|
@NotNull
|
||||||
|
@Min(0)
|
||||||
|
@Valid
|
||||||
|
private Integer refreshIntervalMinutes;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Valid
|
||||||
private CacheType cache;
|
private CacheType cache;
|
||||||
|
|
||||||
@JsonProperty
|
@NotNull
|
||||||
|
@Valid
|
||||||
private String announcement;
|
private String announcement;
|
||||||
|
|
||||||
public Date getUnreadThreshold() {
|
public Date getUnreadThreshold() {
|
||||||
|
|||||||
58
src/main/java/com/commafeed/CommaFeedModule.java
Normal file
58
src/main/java/com/commafeed/CommaFeedModule.java
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package com.commafeed;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import org.hibernate.SessionFactory;
|
||||||
|
|
||||||
|
import com.codahale.metrics.MetricRegistry;
|
||||||
|
import com.commafeed.CommaFeedConfiguration.CacheType;
|
||||||
|
import com.commafeed.backend.cache.CacheService;
|
||||||
|
import com.commafeed.backend.cache.NoopCacheService;
|
||||||
|
import com.commafeed.backend.cache.RedisCacheService;
|
||||||
|
import com.commafeed.backend.favicon.AbstractFaviconFetcher;
|
||||||
|
import com.commafeed.backend.favicon.DefaultFaviconFetcher;
|
||||||
|
import com.commafeed.backend.favicon.FacebookFaviconFetcher;
|
||||||
|
import com.commafeed.backend.favicon.YoutubeFaviconFetcher;
|
||||||
|
import com.commafeed.backend.task.OldEntriesCleanupTask;
|
||||||
|
import com.commafeed.backend.task.OldStatusesCleanupTask;
|
||||||
|
import com.commafeed.backend.task.OrphanedContentsCleanupTask;
|
||||||
|
import com.commafeed.backend.task.OrphanedFeedsCleanupTask;
|
||||||
|
import com.commafeed.backend.task.ScheduledTask;
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
import com.google.inject.Provides;
|
||||||
|
import com.google.inject.multibindings.Multibinder;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Slf4j
|
||||||
|
public class CommaFeedModule extends AbstractModule {
|
||||||
|
|
||||||
|
@Getter(onMethod = @__({ @Provides }))
|
||||||
|
private final SessionFactory sessionFactory;
|
||||||
|
|
||||||
|
@Getter(onMethod = @__({ @Provides }))
|
||||||
|
private final CommaFeedConfiguration config;
|
||||||
|
|
||||||
|
@Getter(onMethod = @__({ @Provides }))
|
||||||
|
private final MetricRegistry metrics;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
CacheService cacheService = config.getApplicationSettings().getCache() == CacheType.NOOP ? new NoopCacheService()
|
||||||
|
: new RedisCacheService(config.getRedisPoolFactory().build());
|
||||||
|
log.info("using cache {}", cacheService.getClass());
|
||||||
|
bind(CacheService.class).toInstance(cacheService);
|
||||||
|
|
||||||
|
Multibinder<AbstractFaviconFetcher> faviconMultibinder = Multibinder.newSetBinder(binder(), AbstractFaviconFetcher.class);
|
||||||
|
faviconMultibinder.addBinding().to(YoutubeFaviconFetcher.class);
|
||||||
|
faviconMultibinder.addBinding().to(FacebookFaviconFetcher.class);
|
||||||
|
faviconMultibinder.addBinding().to(DefaultFaviconFetcher.class);
|
||||||
|
|
||||||
|
Multibinder<ScheduledTask> taskMultibinder = Multibinder.newSetBinder(binder(), ScheduledTask.class);
|
||||||
|
taskMultibinder.addBinding().to(OldStatusesCleanupTask.class);
|
||||||
|
taskMultibinder.addBinding().to(OldEntriesCleanupTask.class);
|
||||||
|
taskMultibinder.addBinding().to(OrphanedFeedsCleanupTask.class);
|
||||||
|
taskMultibinder.addBinding().to(OrphanedContentsCleanupTask.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package com.commafeed.backend;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.http.Header;
|
||||||
|
import org.apache.http.HeaderElement;
|
||||||
|
import org.apache.http.HttpEntity;
|
||||||
|
import org.apache.http.HttpException;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.HttpResponseInterceptor;
|
||||||
|
import org.apache.http.entity.HttpEntityWrapper;
|
||||||
|
import org.apache.http.protocol.HttpContext;
|
||||||
|
|
||||||
|
class ContentEncodingInterceptor implements HttpResponseInterceptor {
|
||||||
|
|
||||||
|
private static final Set<String> ALLOWED_CONTENT_ENCODINGS = new HashSet<>(Arrays.asList("gzip", "x-gzip", "deflate", "identity"));
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(HttpResponse response, HttpContext context) throws HttpException, IOException {
|
||||||
|
if (hasContent(response)) {
|
||||||
|
Header contentEncodingHeader = response.getEntity().getContentEncoding();
|
||||||
|
if (contentEncodingHeader != null && containsUnsupportedEncodings(contentEncodingHeader)) {
|
||||||
|
overrideContentEncoding(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean containsUnsupportedEncodings(Header contentEncodingHeader) {
|
||||||
|
HeaderElement[] codecs = contentEncodingHeader.getElements();
|
||||||
|
|
||||||
|
for (final HeaderElement codec : codecs) {
|
||||||
|
String codecName = codec.getName().toLowerCase(Locale.US);
|
||||||
|
if (!ALLOWED_CONTENT_ENCODINGS.contains(codecName)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void overrideContentEncoding(HttpResponse response) {
|
||||||
|
HttpEntity wrapped = new HttpEntityWrapper(response.getEntity()) {
|
||||||
|
@Override
|
||||||
|
public Header getContentEncoding() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
response.setEntity(wrapped);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasContent(HttpResponse response) {
|
||||||
|
return response.getEntity() != null && response.getEntity().getContentLength() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -4,27 +4,25 @@ import java.io.IOException;
|
|||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
import javax.net.ssl.KeyManager;
|
import javax.net.ssl.KeyManager;
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
import javax.net.ssl.TrustManager;
|
import javax.net.ssl.TrustManager;
|
||||||
import javax.net.ssl.X509TrustManager;
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.http.Consts;
|
import org.apache.http.Consts;
|
||||||
import org.apache.http.Header;
|
import org.apache.http.Header;
|
||||||
import org.apache.http.HeaderElement;
|
|
||||||
import org.apache.http.HttpEntity;
|
import org.apache.http.HttpEntity;
|
||||||
import org.apache.http.HttpException;
|
|
||||||
import org.apache.http.HttpHeaders;
|
import org.apache.http.HttpHeaders;
|
||||||
import org.apache.http.HttpHost;
|
import org.apache.http.HttpHost;
|
||||||
import org.apache.http.HttpResponse;
|
|
||||||
import org.apache.http.HttpResponseInterceptor;
|
import org.apache.http.HttpResponseInterceptor;
|
||||||
import org.apache.http.HttpStatus;
|
import org.apache.http.HttpStatus;
|
||||||
import org.apache.http.client.ClientProtocolException;
|
import org.apache.http.client.ClientProtocolException;
|
||||||
@@ -36,51 +34,27 @@ import org.apache.http.client.methods.HttpGet;
|
|||||||
import org.apache.http.client.methods.HttpUriRequest;
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
import org.apache.http.client.protocol.HttpClientContext;
|
import org.apache.http.client.protocol.HttpClientContext;
|
||||||
import org.apache.http.config.ConnectionConfig;
|
import org.apache.http.config.ConnectionConfig;
|
||||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
import org.apache.http.conn.ssl.NoopHostnameVerifier;
|
||||||
import org.apache.http.entity.HttpEntityWrapper;
|
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
import org.apache.http.impl.client.HttpClientBuilder;
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
import org.apache.http.impl.client.HttpClients;
|
import org.apache.http.impl.client.HttpClients;
|
||||||
import org.apache.http.protocol.HttpContext;
|
|
||||||
import org.apache.http.util.EntityUtils;
|
import org.apache.http.util.EntityUtils;
|
||||||
|
|
||||||
|
import com.commafeed.CommaFeedConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Smart HTTP getter: handles gzip, ssl, last modified and etag headers
|
* Smart HTTP getter: handles gzip, ssl, last modified and etag headers
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@Singleton
|
||||||
public class HttpGetter {
|
public class HttpGetter {
|
||||||
|
|
||||||
private static final String USER_AGENT = "CommaFeed/1.0 (http://www.commafeed.com)";
|
|
||||||
private static final String ACCEPT_LANGUAGE = "en";
|
private static final String ACCEPT_LANGUAGE = "en";
|
||||||
private static final String PRAGMA_NO_CACHE = "No-cache";
|
private static final String PRAGMA_NO_CACHE = "No-cache";
|
||||||
private static final String CACHE_CONTROL_NO_CACHE = "no-cache";
|
private static final String CACHE_CONTROL_NO_CACHE = "no-cache";
|
||||||
|
|
||||||
private static final List<String> ALLOWED_CONTENT_ENCODINGS = Arrays.asList("gzip", "x-gzip", "deflate", "identity");
|
private static final HttpResponseInterceptor REMOVE_INCORRECT_CONTENT_ENCODING = new ContentEncodingInterceptor();
|
||||||
private static final HttpResponseInterceptor REMOVE_INCORRECT_CONTENT_ENCODING = new HttpResponseInterceptor() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(HttpResponse response, HttpContext context) throws HttpException, IOException {
|
|
||||||
HttpEntity entity = response.getEntity();
|
|
||||||
if (entity != null && entity.getContentLength() != 0) {
|
|
||||||
Header header = entity.getContentEncoding();
|
|
||||||
if (header != null) {
|
|
||||||
HeaderElement[] codecs = header.getElements();
|
|
||||||
for (final HeaderElement codec : codecs) {
|
|
||||||
String codecName = codec.getName().toLowerCase(Locale.US);
|
|
||||||
if (!ALLOWED_CONTENT_ENCODINGS.contains(codecName)) {
|
|
||||||
response.setEntity(new HttpEntityWrapper(entity) {
|
|
||||||
@Override
|
|
||||||
public Header getContentEncoding() {
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private static SSLContext SSL_CONTEXT = null;
|
private static SSLContext SSL_CONTEXT = null;
|
||||||
static {
|
static {
|
||||||
@@ -92,6 +66,13 @@ public class HttpGetter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String userAgent;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public HttpGetter(CommaFeedConfiguration config) {
|
||||||
|
this.userAgent = String.format("CommaFeed/%s (https://github.com/Athou/commafeed)", config.getVersion());
|
||||||
|
}
|
||||||
|
|
||||||
public HttpResult getBinary(String url, int timeout) throws ClientProtocolException, IOException, NotModifiedException {
|
public HttpResult getBinary(String url, int timeout) throws ClientProtocolException, IOException, NotModifiedException {
|
||||||
return getBinary(url, null, null, timeout);
|
return getBinary(url, null, null, timeout);
|
||||||
}
|
}
|
||||||
@@ -124,7 +105,7 @@ public class HttpGetter {
|
|||||||
httpget.addHeader(HttpHeaders.ACCEPT_LANGUAGE, ACCEPT_LANGUAGE);
|
httpget.addHeader(HttpHeaders.ACCEPT_LANGUAGE, ACCEPT_LANGUAGE);
|
||||||
httpget.addHeader(HttpHeaders.PRAGMA, PRAGMA_NO_CACHE);
|
httpget.addHeader(HttpHeaders.PRAGMA, PRAGMA_NO_CACHE);
|
||||||
httpget.addHeader(HttpHeaders.CACHE_CONTROL, CACHE_CONTROL_NO_CACHE);
|
httpget.addHeader(HttpHeaders.CACHE_CONTROL, CACHE_CONTROL_NO_CACHE);
|
||||||
httpget.addHeader(HttpHeaders.USER_AGENT, USER_AGENT);
|
httpget.addHeader(HttpHeaders.USER_AGENT, userAgent);
|
||||||
|
|
||||||
if (lastModified != null) {
|
if (lastModified != null) {
|
||||||
httpget.addHeader(HttpHeaders.IF_MODIFIED_SINCE, lastModified);
|
httpget.addHeader(HttpHeaders.IF_MODIFIED_SINCE, lastModified);
|
||||||
@@ -183,47 +164,15 @@ public class HttpGetter {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
public static class HttpResult {
|
public static class HttpResult {
|
||||||
|
private final byte[] content;
|
||||||
private byte[] content;
|
private final String contentType;
|
||||||
private String contentType;
|
private final String lastModifiedSince;
|
||||||
private String lastModifiedSince;
|
private final String eTag;
|
||||||
private String eTag;
|
private final long duration;
|
||||||
private long duration;
|
private final String urlAfterRedirect;
|
||||||
private String urlAfterRedirect;
|
|
||||||
|
|
||||||
public HttpResult(byte[] content, String contentType, String lastModifiedSince, String eTag, long duration, String urlAfterRedirect) {
|
|
||||||
this.content = content;
|
|
||||||
this.contentType = contentType;
|
|
||||||
this.lastModifiedSince = lastModifiedSince;
|
|
||||||
this.eTag = eTag;
|
|
||||||
this.duration = duration;
|
|
||||||
this.urlAfterRedirect = urlAfterRedirect;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getContent() {
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getContentType() {
|
|
||||||
return contentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLastModifiedSince() {
|
|
||||||
return lastModifiedSince;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String geteTag() {
|
|
||||||
return eTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getDuration() {
|
|
||||||
return duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUrlAfterRedirect() {
|
|
||||||
return urlAfterRedirect;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CloseableHttpClient newClient(int timeout) {
|
public static CloseableHttpClient newClient(int timeout) {
|
||||||
@@ -232,8 +181,8 @@ public class HttpGetter {
|
|||||||
builder.addInterceptorFirst(REMOVE_INCORRECT_CONTENT_ENCODING);
|
builder.addInterceptorFirst(REMOVE_INCORRECT_CONTENT_ENCODING);
|
||||||
builder.disableAutomaticRetries();
|
builder.disableAutomaticRetries();
|
||||||
|
|
||||||
builder.setSslcontext(SSL_CONTEXT);
|
builder.setSSLContext(SSL_CONTEXT);
|
||||||
builder.setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
|
builder.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE);
|
||||||
|
|
||||||
RequestConfig.Builder configBuilder = RequestConfig.custom();
|
RequestConfig.Builder configBuilder = RequestConfig.custom();
|
||||||
configBuilder.setCookieSpec(CookieSpecs.IGNORE_COOKIES);
|
configBuilder.setCookieSpec(CookieSpecs.IGNORE_COOKIES);
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
package com.commafeed.backend.cache;
|
package com.commafeed.backend.cache;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.Jedis;
|
||||||
import redis.clients.jedis.JedisPool;
|
import redis.clients.jedis.JedisPool;
|
||||||
import redis.clients.jedis.JedisPoolConfig;
|
|
||||||
import redis.clients.jedis.Pipeline;
|
import redis.clients.jedis.Pipeline;
|
||||||
|
|
||||||
import com.commafeed.backend.model.Feed;
|
import com.commafeed.backend.model.Feed;
|
||||||
@@ -18,41 +19,31 @@ import com.commafeed.frontend.model.Category;
|
|||||||
import com.commafeed.frontend.model.UnreadCount;
|
import com.commafeed.frontend.model.UnreadCount;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class RedisCacheService extends CacheService {
|
public class RedisCacheService extends CacheService {
|
||||||
|
|
||||||
private static ObjectMapper mapper = new ObjectMapper();
|
private static ObjectMapper MAPPER = new ObjectMapper();
|
||||||
|
|
||||||
private JedisPool pool;
|
private final JedisPool pool;
|
||||||
|
|
||||||
public RedisCacheService() {
|
|
||||||
JedisPoolConfig config = new JedisPoolConfig();
|
|
||||||
config.setBlockWhenExhausted(false);
|
|
||||||
pool = new JedisPool(config, "localhost");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getLastEntries(Feed feed) {
|
public List<String> getLastEntries(Feed feed) {
|
||||||
List<String> list = Lists.newArrayList();
|
List<String> list = new ArrayList<>();
|
||||||
Jedis jedis = pool.getResource();
|
try (Jedis jedis = pool.getResource()) {
|
||||||
try {
|
|
||||||
String key = buildRedisEntryKey(feed);
|
String key = buildRedisEntryKey(feed);
|
||||||
Set<String> members = jedis.smembers(key);
|
Set<String> members = jedis.smembers(key);
|
||||||
for (String member : members) {
|
for (String member : members) {
|
||||||
list.add(member);
|
list.add(member);
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
pool.returnResource(jedis);
|
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setLastEntries(Feed feed, List<String> entries) {
|
public void setLastEntries(Feed feed, List<String> entries) {
|
||||||
Jedis jedis = pool.getResource();
|
try (Jedis jedis = pool.getResource()) {
|
||||||
try {
|
|
||||||
String key = buildRedisEntryKey(feed);
|
String key = buildRedisEntryKey(feed);
|
||||||
|
|
||||||
Pipeline pipe = jedis.pipelined();
|
Pipeline pipe = jedis.pipelined();
|
||||||
@@ -62,87 +53,72 @@ public class RedisCacheService extends CacheService {
|
|||||||
}
|
}
|
||||||
pipe.expire(key, (int) TimeUnit.DAYS.toSeconds(7));
|
pipe.expire(key, (int) TimeUnit.DAYS.toSeconds(7));
|
||||||
pipe.sync();
|
pipe.sync();
|
||||||
} finally {
|
|
||||||
pool.returnResource(jedis);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Category getUserRootCategory(User user) {
|
public Category getUserRootCategory(User user) {
|
||||||
Category cat = null;
|
Category cat = null;
|
||||||
Jedis jedis = pool.getResource();
|
try (Jedis jedis = pool.getResource()) {
|
||||||
try {
|
|
||||||
String key = buildRedisUserRootCategoryKey(user);
|
String key = buildRedisUserRootCategoryKey(user);
|
||||||
String json = jedis.get(key);
|
String json = jedis.get(key);
|
||||||
if (json != null) {
|
if (json != null) {
|
||||||
cat = mapper.readValue(json, Category.class);
|
cat = MAPPER.readValue(json, Category.class);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error(e.getMessage(), e);
|
log.error(e.getMessage(), e);
|
||||||
} finally {
|
|
||||||
pool.returnResource(jedis);
|
|
||||||
}
|
}
|
||||||
return cat;
|
return cat;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setUserRootCategory(User user, Category category) {
|
public void setUserRootCategory(User user, Category category) {
|
||||||
Jedis jedis = pool.getResource();
|
try (Jedis jedis = pool.getResource()) {
|
||||||
try {
|
|
||||||
String key = buildRedisUserRootCategoryKey(user);
|
String key = buildRedisUserRootCategoryKey(user);
|
||||||
|
|
||||||
Pipeline pipe = jedis.pipelined();
|
Pipeline pipe = jedis.pipelined();
|
||||||
pipe.del(key);
|
pipe.del(key);
|
||||||
pipe.set(key, mapper.writeValueAsString(category));
|
pipe.set(key, MAPPER.writeValueAsString(category));
|
||||||
pipe.expire(key, (int) TimeUnit.MINUTES.toSeconds(30));
|
pipe.expire(key, (int) TimeUnit.MINUTES.toSeconds(30));
|
||||||
pipe.sync();
|
pipe.sync();
|
||||||
} catch (JsonProcessingException e) {
|
} catch (JsonProcessingException e) {
|
||||||
log.error(e.getMessage(), e);
|
log.error(e.getMessage(), e);
|
||||||
} finally {
|
|
||||||
pool.returnResource(jedis);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UnreadCount getUnreadCount(FeedSubscription sub) {
|
public UnreadCount getUnreadCount(FeedSubscription sub) {
|
||||||
UnreadCount count = null;
|
UnreadCount count = null;
|
||||||
Jedis jedis = pool.getResource();
|
try (Jedis jedis = pool.getResource()) {
|
||||||
try {
|
|
||||||
String key = buildRedisUnreadCountKey(sub);
|
String key = buildRedisUnreadCountKey(sub);
|
||||||
String json = jedis.get(key);
|
String json = jedis.get(key);
|
||||||
if (json != null) {
|
if (json != null) {
|
||||||
count = mapper.readValue(json, UnreadCount.class);
|
count = MAPPER.readValue(json, UnreadCount.class);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error(e.getMessage(), e);
|
log.error(e.getMessage(), e);
|
||||||
} finally {
|
|
||||||
pool.returnResource(jedis);
|
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setUnreadCount(FeedSubscription sub, UnreadCount count) {
|
public void setUnreadCount(FeedSubscription sub, UnreadCount count) {
|
||||||
Jedis jedis = pool.getResource();
|
try (Jedis jedis = pool.getResource()) {
|
||||||
try {
|
|
||||||
String key = buildRedisUnreadCountKey(sub);
|
String key = buildRedisUnreadCountKey(sub);
|
||||||
|
|
||||||
Pipeline pipe = jedis.pipelined();
|
Pipeline pipe = jedis.pipelined();
|
||||||
pipe.del(key);
|
pipe.del(key);
|
||||||
pipe.set(key, mapper.writeValueAsString(count));
|
pipe.set(key, MAPPER.writeValueAsString(count));
|
||||||
pipe.expire(key, (int) TimeUnit.MINUTES.toSeconds(30));
|
pipe.expire(key, (int) TimeUnit.MINUTES.toSeconds(30));
|
||||||
pipe.sync();
|
pipe.sync();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error(e.getMessage(), e);
|
log.error(e.getMessage(), e);
|
||||||
} finally {
|
|
||||||
pool.returnResource(jedis);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void invalidateUserRootCategory(User... users) {
|
public void invalidateUserRootCategory(User... users) {
|
||||||
Jedis jedis = pool.getResource();
|
try (Jedis jedis = pool.getResource()) {
|
||||||
try {
|
|
||||||
Pipeline pipe = jedis.pipelined();
|
Pipeline pipe = jedis.pipelined();
|
||||||
if (users != null) {
|
if (users != null) {
|
||||||
for (User user : users) {
|
for (User user : users) {
|
||||||
@@ -151,15 +127,12 @@ public class RedisCacheService extends CacheService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
pipe.sync();
|
pipe.sync();
|
||||||
} finally {
|
|
||||||
pool.returnResource(jedis);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void invalidateUnreadCount(FeedSubscription... subs) {
|
public void invalidateUnreadCount(FeedSubscription... subs) {
|
||||||
Jedis jedis = pool.getResource();
|
try (Jedis jedis = pool.getResource()) {
|
||||||
try {
|
|
||||||
Pipeline pipe = jedis.pipelined();
|
Pipeline pipe = jedis.pipelined();
|
||||||
if (subs != null) {
|
if (subs != null) {
|
||||||
for (FeedSubscription sub : subs) {
|
for (FeedSubscription sub : subs) {
|
||||||
@@ -168,8 +141,6 @@ public class RedisCacheService extends CacheService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
pipe.sync();
|
pipe.sync();
|
||||||
} finally {
|
|
||||||
pool.returnResource(jedis);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
28
src/main/java/com/commafeed/backend/cache/RedisPoolFactory.java
vendored
Normal file
28
src/main/java/com/commafeed/backend/cache/RedisPoolFactory.java
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package com.commafeed.backend.cache;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import redis.clients.jedis.JedisPool;
|
||||||
|
import redis.clients.jedis.JedisPoolConfig;
|
||||||
|
import redis.clients.jedis.Protocol;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class RedisPoolFactory {
|
||||||
|
private String host = "localhost";
|
||||||
|
private int port = Protocol.DEFAULT_PORT;
|
||||||
|
private String password = null;
|
||||||
|
private int timeout = Protocol.DEFAULT_TIMEOUT;
|
||||||
|
private int database = Protocol.DEFAULT_DATABASE;
|
||||||
|
|
||||||
|
private int maxTotal = 500;
|
||||||
|
|
||||||
|
public JedisPool build() {
|
||||||
|
JedisPoolConfig config = new JedisPoolConfig();
|
||||||
|
config.setMaxTotal(maxTotal);
|
||||||
|
|
||||||
|
return new JedisPool(config, host, port, timeout, StringUtils.trimToNull(password), database);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,31 +1,36 @@
|
|||||||
package com.commafeed.backend.dao;
|
package com.commafeed.backend.dao;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.apache.commons.lang.ObjectUtils;
|
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
|
|
||||||
import com.commafeed.backend.model.FeedCategory;
|
import com.commafeed.backend.model.FeedCategory;
|
||||||
import com.commafeed.backend.model.QFeedCategory;
|
import com.commafeed.backend.model.QFeedCategory;
|
||||||
import com.commafeed.backend.model.QUser;
|
import com.commafeed.backend.model.QUser;
|
||||||
import com.commafeed.backend.model.User;
|
import com.commafeed.backend.model.User;
|
||||||
import com.google.common.collect.Lists;
|
import com.querydsl.core.types.Predicate;
|
||||||
import com.mysema.query.types.Predicate;
|
|
||||||
|
|
||||||
|
@Singleton
|
||||||
public class FeedCategoryDAO extends GenericDAO<FeedCategory> {
|
public class FeedCategoryDAO extends GenericDAO<FeedCategory> {
|
||||||
|
|
||||||
private QFeedCategory category = QFeedCategory.feedCategory;
|
private QFeedCategory category = QFeedCategory.feedCategory;
|
||||||
|
|
||||||
|
@Inject
|
||||||
public FeedCategoryDAO(SessionFactory sessionFactory) {
|
public FeedCategoryDAO(SessionFactory sessionFactory) {
|
||||||
super(sessionFactory);
|
super(sessionFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<FeedCategory> findAll(User user) {
|
public List<FeedCategory> findAll(User user) {
|
||||||
return newQuery().from(category).where(category.user.eq(user)).join(category.user, QUser.user).fetch().list(category);
|
return query().selectFrom(category).where(category.user.eq(user)).join(category.user, QUser.user).fetchJoin().fetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
public FeedCategory findById(User user, Long id) {
|
public FeedCategory findById(User user, Long id) {
|
||||||
return newQuery().from(category).where(category.user.eq(user), category.id.eq(id)).uniqueResult(category);
|
return query().selectFrom(category).where(category.user.eq(user), category.id.eq(id)).fetchOne();
|
||||||
}
|
}
|
||||||
|
|
||||||
public FeedCategory findByName(User user, String name, FeedCategory parent) {
|
public FeedCategory findByName(User user, String name, FeedCategory parent) {
|
||||||
@@ -35,7 +40,7 @@ public class FeedCategoryDAO extends GenericDAO<FeedCategory> {
|
|||||||
} else {
|
} else {
|
||||||
parentPredicate = category.parent.eq(parent);
|
parentPredicate = category.parent.eq(parent);
|
||||||
}
|
}
|
||||||
return newQuery().from(category).where(category.user.eq(user), category.name.eq(name), parentPredicate).uniqueResult(category);
|
return query().selectFrom(category).where(category.user.eq(user), category.name.eq(name), parentPredicate).fetchOne();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<FeedCategory> findByParent(User user, FeedCategory parent) {
|
public List<FeedCategory> findByParent(User user, FeedCategory parent) {
|
||||||
@@ -45,27 +50,20 @@ public class FeedCategoryDAO extends GenericDAO<FeedCategory> {
|
|||||||
} else {
|
} else {
|
||||||
parentPredicate = category.parent.eq(parent);
|
parentPredicate = category.parent.eq(parent);
|
||||||
}
|
}
|
||||||
return newQuery().from(category).where(category.user.eq(user), parentPredicate).list(category);
|
return query().selectFrom(category).where(category.user.eq(user), parentPredicate).fetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<FeedCategory> findAllChildrenCategories(User user, FeedCategory parent) {
|
public List<FeedCategory> findAllChildrenCategories(User user, FeedCategory parent) {
|
||||||
List<FeedCategory> list = Lists.newArrayList();
|
return findAll(user).stream().filter(c -> isChild(c, parent)).collect(Collectors.toList());
|
||||||
List<FeedCategory> all = findAll(user);
|
|
||||||
for (FeedCategory cat : all) {
|
|
||||||
if (isChild(cat, parent)) {
|
|
||||||
list.add(cat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isChild(FeedCategory child, FeedCategory parent) {
|
private boolean isChild(FeedCategory child, FeedCategory parent) {
|
||||||
if (parent == null) {
|
if (parent == null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
boolean isChild = false;
|
boolean isChild = false;
|
||||||
while (child != null) {
|
while (child != null) {
|
||||||
if (ObjectUtils.equals(child.getId(), parent.getId())) {
|
if (Objects.equals(child.getId(), parent.getId())) {
|
||||||
isChild = true;
|
isChild = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,11 @@ package com.commafeed.backend.dao;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
|
|
||||||
import com.commafeed.backend.model.Feed;
|
import com.commafeed.backend.model.Feed;
|
||||||
@@ -12,53 +15,38 @@ import com.commafeed.backend.model.QFeed;
|
|||||||
import com.commafeed.backend.model.QFeedSubscription;
|
import com.commafeed.backend.model.QFeedSubscription;
|
||||||
import com.commafeed.backend.model.QUser;
|
import com.commafeed.backend.model.QUser;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.mysema.query.BooleanBuilder;
|
import com.querydsl.jpa.JPAExpressions;
|
||||||
import com.mysema.query.jpa.hibernate.HibernateQuery;
|
import com.querydsl.jpa.JPQLQuery;
|
||||||
import com.mysema.query.jpa.hibernate.HibernateSubQuery;
|
import com.querydsl.jpa.hibernate.HibernateQuery;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
public class FeedDAO extends GenericDAO<Feed> {
|
public class FeedDAO extends GenericDAO<Feed> {
|
||||||
|
|
||||||
private QFeed feed = QFeed.feed;
|
private QFeed feed = QFeed.feed;
|
||||||
|
|
||||||
|
@Inject
|
||||||
public FeedDAO(SessionFactory sessionFactory) {
|
public FeedDAO(SessionFactory sessionFactory) {
|
||||||
super(sessionFactory);
|
super(sessionFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getUpdatableCount(Date lastLoginThreshold) {
|
|
||||||
BooleanBuilder disabledDatePredicate = new BooleanBuilder();
|
|
||||||
disabledDatePredicate.or(feed.disabledUntil.isNull());
|
|
||||||
disabledDatePredicate.or(feed.disabledUntil.lt(new Date()));
|
|
||||||
|
|
||||||
HibernateQuery query = newQuery().from(feed).where(disabledDatePredicate);
|
|
||||||
if (lastLoginThreshold != null) {
|
|
||||||
QFeedSubscription sub = QFeedSubscription.feedSubscription;
|
|
||||||
QUser user = QUser.user;
|
|
||||||
HibernateSubQuery subquery = new HibernateSubQuery();
|
|
||||||
subquery.from(sub).join(sub.user, user).where(sub.feed.eq(feed), user.lastLogin.gt(lastLoginThreshold));
|
|
||||||
query.where(subquery.exists());
|
|
||||||
}
|
|
||||||
return query.orderBy(feed.disabledUntil.asc()).count();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Feed> findNextUpdatable(int count, Date lastLoginThreshold) {
|
public List<Feed> findNextUpdatable(int count, Date lastLoginThreshold) {
|
||||||
BooleanBuilder disabledDatePredicate = new BooleanBuilder();
|
HibernateQuery<Feed> query = query().selectFrom(feed);
|
||||||
disabledDatePredicate.or(feed.disabledUntil.isNull());
|
query.where(feed.disabledUntil.isNull().or(feed.disabledUntil.lt(new Date())));
|
||||||
disabledDatePredicate.or(feed.disabledUntil.lt(new Date()));
|
|
||||||
|
|
||||||
HibernateQuery query = newQuery().from(feed);
|
|
||||||
if (lastLoginThreshold != null) {
|
if (lastLoginThreshold != null) {
|
||||||
QFeedSubscription subs = QFeedSubscription.feedSubscription;
|
QFeedSubscription subs = QFeedSubscription.feedSubscription;
|
||||||
QUser user = QUser.user;
|
QUser user = QUser.user;
|
||||||
query.join(feed.subscriptions, subs).join(subs.user, user).where(disabledDatePredicate, user.lastLogin.gt(lastLoginThreshold));
|
|
||||||
} else {
|
JPQLQuery<Integer> subQuery = JPAExpressions.selectOne().from(subs);
|
||||||
query.where(disabledDatePredicate);
|
subQuery.join(subs.user, user).where(user.lastLogin.gt(lastLoginThreshold));
|
||||||
|
query.where(subQuery.exists());
|
||||||
}
|
}
|
||||||
|
|
||||||
return query.orderBy(feed.disabledUntil.asc()).limit(count).distinct().list(feed);
|
return query.orderBy(feed.disabledUntil.asc()).limit(count).distinct().fetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Feed findByUrl(String normalizedUrl) {
|
public Feed findByUrl(String normalizedUrl) {
|
||||||
List<Feed> feeds = newQuery().from(feed).where(feed.normalizedUrlHash.eq(DigestUtils.sha1Hex(normalizedUrl))).list(feed);
|
List<Feed> feeds = query().selectFrom(feed).where(feed.normalizedUrlHash.eq(DigestUtils.sha1Hex(normalizedUrl))).fetch();
|
||||||
Feed feed = Iterables.getFirst(feeds, null);
|
Feed feed = Iterables.getFirst(feeds, null);
|
||||||
if (feed != null && StringUtils.equals(normalizedUrl, feed.getNormalizedUrl())) {
|
if (feed != null && StringUtils.equals(normalizedUrl, feed.getNormalizedUrl())) {
|
||||||
return feed;
|
return feed;
|
||||||
@@ -67,11 +55,12 @@ public class FeedDAO extends GenericDAO<Feed> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<Feed> findByTopic(String topic) {
|
public List<Feed> findByTopic(String topic) {
|
||||||
return newQuery().from(feed).where(feed.pushTopicHash.eq(DigestUtils.sha1Hex(topic))).list(feed);
|
return query().selectFrom(feed).where(feed.pushTopicHash.eq(DigestUtils.sha1Hex(topic))).fetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Feed> findWithoutSubscriptions(int max) {
|
public List<Feed> findWithoutSubscriptions(int max) {
|
||||||
QFeedSubscription sub = QFeedSubscription.feedSubscription;
|
QFeedSubscription sub = QFeedSubscription.feedSubscription;
|
||||||
return newQuery().from(feed).leftJoin(feed.subscriptions, sub).where(sub.id.isNull()).limit(max).list(feed);
|
return query().selectFrom(feed).where(JPAExpressions.selectOne().from(sub).where(sub.feed.eq(feed)).notExists()).limit(max)
|
||||||
|
.fetch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,32 +2,38 @@ package com.commafeed.backend.dao;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
|
|
||||||
import com.commafeed.backend.model.FeedEntryContent;
|
import com.commafeed.backend.model.FeedEntryContent;
|
||||||
import com.commafeed.backend.model.QFeedEntry;
|
import com.commafeed.backend.model.QFeedEntry;
|
||||||
import com.commafeed.backend.model.QFeedEntryContent;
|
import com.commafeed.backend.model.QFeedEntryContent;
|
||||||
import com.google.common.collect.Iterables;
|
import com.querydsl.jpa.JPAExpressions;
|
||||||
import com.mysema.query.types.ConstructorExpression;
|
import com.querydsl.jpa.JPQLQuery;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
public class FeedEntryContentDAO extends GenericDAO<FeedEntryContent> {
|
public class FeedEntryContentDAO extends GenericDAO<FeedEntryContent> {
|
||||||
|
|
||||||
private QFeedEntryContent content = QFeedEntryContent.feedEntryContent;
|
private QFeedEntryContent content = QFeedEntryContent.feedEntryContent;
|
||||||
|
private QFeedEntry entry = QFeedEntry.feedEntry;
|
||||||
|
|
||||||
|
@Inject
|
||||||
public FeedEntryContentDAO(SessionFactory sessionFactory) {
|
public FeedEntryContentDAO(SessionFactory sessionFactory) {
|
||||||
super(sessionFactory);
|
super(sessionFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long findExisting(String contentHash, String titleHash) {
|
public Long findExisting(String contentHash, String titleHash) {
|
||||||
List<Long> list = newQuery().from(content).where(content.contentHash.eq(contentHash), content.titleHash.eq(titleHash)).limit(1)
|
return query().select(content.id).from(content).where(content.contentHash.eq(contentHash), content.titleHash.eq(titleHash))
|
||||||
.list(ConstructorExpression.create(Long.class, content.id));
|
.fetchFirst();
|
||||||
return Iterables.getFirst(list, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int deleteWithoutEntries(int max) {
|
public int deleteWithoutEntries(int max) {
|
||||||
QFeedEntry entry = QFeedEntry.feedEntry;
|
|
||||||
List<FeedEntryContent> list = newQuery().from(content).leftJoin(content.entries, entry).where(entry.id.isNull()).limit(max)
|
JPQLQuery<Integer> subQuery = JPAExpressions.selectOne().from(entry).where(entry.content.id.eq(content.id));
|
||||||
.list(content);
|
List<FeedEntryContent> list = query().selectFrom(content).where(subQuery.notExists()).limit(max).fetch();
|
||||||
|
|
||||||
int deleted = list.size();
|
int deleted = list.size();
|
||||||
delete(list);
|
delete(list);
|
||||||
return deleted;
|
return deleted;
|
||||||
|
|||||||
@@ -1,51 +1,60 @@
|
|||||||
package com.commafeed.backend.dao;
|
package com.commafeed.backend.dao;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
|
|
||||||
import com.commafeed.backend.model.Feed;
|
import com.commafeed.backend.model.Feed;
|
||||||
import com.commafeed.backend.model.FeedEntry;
|
import com.commafeed.backend.model.FeedEntry;
|
||||||
import com.commafeed.backend.model.QFeed;
|
|
||||||
import com.commafeed.backend.model.QFeedEntry;
|
import com.commafeed.backend.model.QFeedEntry;
|
||||||
import com.commafeed.backend.model.QFeedSubscription;
|
import com.querydsl.core.Tuple;
|
||||||
import com.google.common.collect.Iterables;
|
import com.querydsl.core.types.dsl.NumberExpression;
|
||||||
import com.mysema.query.types.ConstructorExpression;
|
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
public class FeedEntryDAO extends GenericDAO<FeedEntry> {
|
public class FeedEntryDAO extends GenericDAO<FeedEntry> {
|
||||||
|
|
||||||
private QFeedEntry entry = QFeedEntry.feedEntry;
|
private QFeedEntry entry = QFeedEntry.feedEntry;
|
||||||
|
|
||||||
|
@Inject
|
||||||
public FeedEntryDAO(SessionFactory sessionFactory) {
|
public FeedEntryDAO(SessionFactory sessionFactory) {
|
||||||
super(sessionFactory);
|
super(sessionFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long findExisting(String guid, Feed feed) {
|
public Long findExisting(String guid, Feed feed) {
|
||||||
List<Long> list = newQuery().from(entry).where(entry.guidHash.eq(DigestUtils.sha1Hex(guid)), entry.feed.eq(feed)).limit(1)
|
return query().select(entry.id).from(entry).where(entry.guidHash.eq(DigestUtils.sha1Hex(guid)), entry.feed.eq(feed)).limit(1)
|
||||||
.list(ConstructorExpression.create(Long.class, entry.id));
|
.fetchOne();
|
||||||
return Iterables.getFirst(list, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<FeedEntry> findWithoutSubscriptions(int max) {
|
public List<FeedCapacity> findFeedsExceedingCapacity(long maxCapacity, long max) {
|
||||||
QFeed feed = QFeed.feed;
|
NumberExpression<Long> count = entry.id.count();
|
||||||
QFeedSubscription sub = QFeedSubscription.feedSubscription;
|
List<Tuple> tuples = query().select(entry.feed.id, count).from(entry).groupBy(entry.feed).having(count.gt(maxCapacity)).limit(max)
|
||||||
return newQuery().from(entry).join(entry.feed, feed).leftJoin(feed.subscriptions, sub).where(sub.id.isNull()).limit(max)
|
.fetch();
|
||||||
.list(entry);
|
return tuples.stream().map(t -> new FeedCapacity(t.get(entry.feed.id), t.get(count))).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public int delete(Feed feed, int max) {
|
public int delete(Long feedId, long max) {
|
||||||
List<FeedEntry> list = newQuery().from(entry).where(entry.feed.eq(feed)).limit(max).list(entry);
|
|
||||||
int deleted = list.size();
|
List<FeedEntry> list = query().selectFrom(entry).where(entry.feed.id.eq(feedId)).limit(max).fetch();
|
||||||
delete(list);
|
return delete(list);
|
||||||
return deleted;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int delete(Date olderThan, int max) {
|
public int deleteOldEntries(Long feedId, long max) {
|
||||||
List<FeedEntry> list = newQuery().from(entry).where(entry.inserted.lt(olderThan)).limit(max).list(entry);
|
List<FeedEntry> list = query().selectFrom(entry).where(entry.feed.id.eq(feedId)).orderBy(entry.updated.asc()).limit(max).fetch();
|
||||||
int deleted = list.size();
|
return delete(list);
|
||||||
delete(list);
|
}
|
||||||
return deleted;
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public static class FeedCapacity {
|
||||||
|
private Long id;
|
||||||
|
private Long capacity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,21 @@
|
|||||||
package com.commafeed.backend.dao;
|
package com.commafeed.backend.dao;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import javax.inject.Inject;
|
||||||
import org.apache.commons.lang.builder.CompareToBuilder;
|
import javax.inject.Singleton;
|
||||||
import org.hibernate.Criteria;
|
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.builder.CompareToBuilder;
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
import org.hibernate.criterion.Conjunction;
|
|
||||||
import org.hibernate.criterion.Disjunction;
|
|
||||||
import org.hibernate.criterion.MatchMode;
|
|
||||||
import org.hibernate.criterion.Order;
|
|
||||||
import org.hibernate.criterion.ProjectionList;
|
|
||||||
import org.hibernate.criterion.Projections;
|
|
||||||
import org.hibernate.criterion.Restrictions;
|
|
||||||
import org.hibernate.sql.JoinType;
|
|
||||||
import org.hibernate.transform.Transformers;
|
|
||||||
|
|
||||||
import com.commafeed.CommaFeedConfiguration;
|
import com.commafeed.CommaFeedConfiguration;
|
||||||
import com.commafeed.backend.FixedSizeSortedSet;
|
import com.commafeed.backend.FixedSizeSortedSet;
|
||||||
|
import com.commafeed.backend.feed.FeedEntryKeyword;
|
||||||
|
import com.commafeed.backend.feed.FeedEntryKeyword.Mode;
|
||||||
import com.commafeed.backend.model.FeedEntry;
|
import com.commafeed.backend.model.FeedEntry;
|
||||||
import com.commafeed.backend.model.FeedEntryStatus;
|
import com.commafeed.backend.model.FeedEntryStatus;
|
||||||
import com.commafeed.backend.model.FeedEntryTag;
|
import com.commafeed.backend.model.FeedEntryTag;
|
||||||
@@ -34,22 +29,24 @@ import com.commafeed.backend.model.User;
|
|||||||
import com.commafeed.backend.model.UserSettings.ReadingOrder;
|
import com.commafeed.backend.model.UserSettings.ReadingOrder;
|
||||||
import com.commafeed.frontend.model.UnreadCount;
|
import com.commafeed.frontend.model.UnreadCount;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Ordering;
|
import com.google.common.collect.Ordering;
|
||||||
import com.mysema.query.jpa.hibernate.HibernateQuery;
|
import com.querydsl.core.BooleanBuilder;
|
||||||
|
import com.querydsl.core.Tuple;
|
||||||
|
import com.querydsl.jpa.hibernate.HibernateQuery;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||||
|
|
||||||
private static final String ALIAS_STATUS = "status";
|
|
||||||
private static final String ALIAS_ENTRY = "entry";
|
|
||||||
private static final String ALIAS_TAG = "tag";
|
|
||||||
|
|
||||||
private FeedEntryDAO feedEntryDAO;
|
private FeedEntryDAO feedEntryDAO;
|
||||||
private FeedEntryTagDAO feedEntryTagDAO;
|
private FeedEntryTagDAO feedEntryTagDAO;
|
||||||
private CommaFeedConfiguration config;
|
private CommaFeedConfiguration config;
|
||||||
|
|
||||||
private QFeedEntryStatus status = QFeedEntryStatus.feedEntryStatus;
|
private QFeedEntryStatus status = QFeedEntryStatus.feedEntryStatus;
|
||||||
|
private QFeedEntry entry = QFeedEntry.feedEntry;
|
||||||
|
private QFeedEntryContent content = QFeedEntryContent.feedEntryContent;
|
||||||
|
private QFeedEntryTag entryTag = QFeedEntryTag.feedEntryTag;
|
||||||
|
|
||||||
|
@Inject
|
||||||
public FeedEntryStatusDAO(SessionFactory sessionFactory, FeedEntryDAO feedEntryDAO, FeedEntryTagDAO feedEntryTagDAO,
|
public FeedEntryStatusDAO(SessionFactory sessionFactory, FeedEntryDAO feedEntryDAO, FeedEntryTagDAO feedEntryTagDAO,
|
||||||
CommaFeedConfiguration config) {
|
CommaFeedConfiguration config) {
|
||||||
super(sessionFactory);
|
super(sessionFactory);
|
||||||
@@ -65,13 +62,13 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
|||||||
builder.append(o2.getEntryUpdated(), o1.getEntryUpdated());
|
builder.append(o2.getEntryUpdated(), o1.getEntryUpdated());
|
||||||
builder.append(o2.getId(), o1.getId());
|
builder.append(o2.getId(), o1.getId());
|
||||||
return builder.toComparison();
|
return builder.toComparison();
|
||||||
};
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final Comparator<FeedEntryStatus> STATUS_COMPARATOR_ASC = Ordering.from(STATUS_COMPARATOR_DESC).reverse();
|
private static final Comparator<FeedEntryStatus> STATUS_COMPARATOR_ASC = Ordering.from(STATUS_COMPARATOR_DESC).reverse();
|
||||||
|
|
||||||
public FeedEntryStatus getStatus(User user, FeedSubscription sub, FeedEntry entry) {
|
public FeedEntryStatus getStatus(User user, FeedSubscription sub, FeedEntry entry) {
|
||||||
List<FeedEntryStatus> statuses = newQuery().from(status).where(status.entry.eq(entry), status.subscription.eq(sub)).list(status);
|
List<FeedEntryStatus> statuses = query().selectFrom(status).where(status.entry.eq(entry), status.subscription.eq(sub)).fetch();
|
||||||
FeedEntryStatus status = Iterables.getFirst(statuses, null);
|
FeedEntryStatus status = Iterables.getFirst(statuses, null);
|
||||||
return handleStatus(user, status, sub, entry);
|
return handleStatus(user, status, sub, entry);
|
||||||
}
|
}
|
||||||
@@ -96,7 +93,7 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<FeedEntryStatus> findStarred(User user, Date newerThan, int offset, int limit, ReadingOrder order, boolean includeContent) {
|
public List<FeedEntryStatus> findStarred(User user, Date newerThan, int offset, int limit, ReadingOrder order, boolean includeContent) {
|
||||||
HibernateQuery query = newQuery().from(status).where(status.user.eq(user), status.starred.isTrue());
|
HibernateQuery<FeedEntryStatus> query = query().selectFrom(status).where(status.user.eq(user), status.starred.isTrue());
|
||||||
if (newerThan != null) {
|
if (newerThan != null) {
|
||||||
query.where(status.entryInserted.gt(newerThan));
|
query.where(status.entryInserted.gt(newerThan));
|
||||||
}
|
}
|
||||||
@@ -107,112 +104,105 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
|||||||
query.orderBy(status.entryUpdated.desc(), status.id.desc());
|
query.orderBy(status.entryUpdated.desc(), status.id.desc());
|
||||||
}
|
}
|
||||||
|
|
||||||
query.offset(offset).limit(limit).setTimeout(config.getApplicationSettings().getQueryTimeout());
|
query.offset(offset).limit(limit);
|
||||||
|
int timeout = config.getApplicationSettings().getQueryTimeout();
|
||||||
|
if (timeout > 0) {
|
||||||
|
query.setTimeout(timeout / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
List<FeedEntryStatus> statuses = query.list(status);
|
List<FeedEntryStatus> statuses = query.fetch();
|
||||||
for (FeedEntryStatus status : statuses) {
|
for (FeedEntryStatus status : statuses) {
|
||||||
status = handleStatus(user, status, status.getSubscription(), status.getEntry());
|
status = handleStatus(user, status, status.getSubscription(), status.getEntry());
|
||||||
status = fetchTags(user, status);
|
fetchTags(user, status);
|
||||||
}
|
}
|
||||||
return lazyLoadContent(includeContent, statuses);
|
return lazyLoadContent(includeContent, statuses);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Criteria buildSearchCriteria(User user, FeedSubscription sub, boolean unreadOnly, String keywords, Date newerThan, int offset,
|
private HibernateQuery<FeedEntry> buildQuery(User user, FeedSubscription sub, boolean unreadOnly, List<FeedEntryKeyword> keywords,
|
||||||
int limit, ReadingOrder order, Date last, String tag) {
|
Date newerThan, int offset, int limit, ReadingOrder order, Date last, String tag) {
|
||||||
QFeedEntry entry = QFeedEntry.feedEntry;
|
|
||||||
QFeedEntryContent content = QFeedEntryContent.feedEntryContent;
|
|
||||||
QFeedEntryStatus status = QFeedEntryStatus.feedEntryStatus;
|
|
||||||
QFeedEntryTag entryTag = QFeedEntryTag.feedEntryTag;
|
|
||||||
|
|
||||||
Criteria criteria = currentSession().createCriteria(FeedEntry.class, ALIAS_ENTRY);
|
HibernateQuery<FeedEntry> query = query().selectFrom(entry).where(entry.feed.eq(sub.getFeed()));
|
||||||
criteria.add(Restrictions.eq(entry.feed.getMetadata().getName(), sub.getFeed()));
|
|
||||||
|
|
||||||
if (keywords != null) {
|
if (CollectionUtils.isNotEmpty(keywords)) {
|
||||||
Criteria contentJoin = criteria.createCriteria(entry.content.getMetadata().getName(), "content", JoinType.INNER_JOIN);
|
query.join(entry.content, content);
|
||||||
|
|
||||||
for (String keyword : StringUtils.split(keywords)) {
|
for (FeedEntryKeyword keyword : keywords) {
|
||||||
Disjunction or = Restrictions.disjunction();
|
BooleanBuilder or = new BooleanBuilder();
|
||||||
or.add(Restrictions.ilike(content.content.getMetadata().getName(), keyword, MatchMode.ANYWHERE));
|
or.or(content.content.containsIgnoreCase(keyword.getKeyword()));
|
||||||
or.add(Restrictions.ilike(content.title.getMetadata().getName(), keyword, MatchMode.ANYWHERE));
|
or.or(content.title.containsIgnoreCase(keyword.getKeyword()));
|
||||||
contentJoin.add(or);
|
if (keyword.getMode() == Mode.EXCLUDE) {
|
||||||
|
or.not();
|
||||||
|
}
|
||||||
|
query.where(or);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Criteria statusJoin = criteria.createCriteria(entry.statuses.getMetadata().getName(), ALIAS_STATUS, JoinType.LEFT_OUTER_JOIN,
|
query.leftJoin(entry.statuses, status).on(status.subscription.id.eq(sub.getId()));
|
||||||
Restrictions.eq(status.subscription.getMetadata().getName(), sub));
|
|
||||||
|
|
||||||
if (unreadOnly && tag == null) {
|
if (unreadOnly && tag == null) {
|
||||||
|
BooleanBuilder or = new BooleanBuilder();
|
||||||
Disjunction or = Restrictions.disjunction();
|
or.or(status.read.isNull());
|
||||||
or.add(Restrictions.isNull(status.read.getMetadata().getName()));
|
or.or(status.read.isFalse());
|
||||||
or.add(Restrictions.eq(status.read.getMetadata().getName(), false));
|
query.where(or);
|
||||||
statusJoin.add(or);
|
|
||||||
|
|
||||||
Date unreadThreshold = config.getApplicationSettings().getUnreadThreshold();
|
Date unreadThreshold = config.getApplicationSettings().getUnreadThreshold();
|
||||||
if (unreadThreshold != null) {
|
if (unreadThreshold != null) {
|
||||||
criteria.add(Restrictions.ge(entry.updated.getMetadata().getName(), unreadThreshold));
|
query.where(entry.updated.goe(unreadThreshold));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tag != null) {
|
if (tag != null) {
|
||||||
Conjunction and = Restrictions.conjunction();
|
BooleanBuilder and = new BooleanBuilder();
|
||||||
and.add(Restrictions.eq(entryTag.user.getMetadata().getName(), user));
|
and.and(entryTag.user.id.eq(user.getId()));
|
||||||
and.add(Restrictions.eq(entryTag.name.getMetadata().getName(), tag));
|
and.and(entryTag.name.eq(tag));
|
||||||
criteria.createCriteria(entry.tags.getMetadata().getName(), ALIAS_TAG, JoinType.INNER_JOIN, and);
|
query.join(entry.tags, entryTag).on(and);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newerThan != null) {
|
if (newerThan != null) {
|
||||||
criteria.add(Restrictions.ge(entry.inserted.getMetadata().getName(), newerThan));
|
query.where(entry.inserted.goe(newerThan));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last != null) {
|
if (last != null) {
|
||||||
if (order == ReadingOrder.desc) {
|
if (order == ReadingOrder.desc) {
|
||||||
criteria.add(Restrictions.gt(entry.updated.getMetadata().getName(), last));
|
query.where(entry.updated.gt(last));
|
||||||
} else {
|
} else {
|
||||||
criteria.add(Restrictions.lt(entry.updated.getMetadata().getName(), last));
|
query.where(entry.updated.lt(last));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (order != null) {
|
if (order != null) {
|
||||||
if (order == ReadingOrder.asc) {
|
if (order == ReadingOrder.asc) {
|
||||||
criteria.addOrder(Order.asc(entry.updated.getMetadata().getName())).addOrder(Order.asc(entry.id.getMetadata().getName()));
|
query.orderBy(entry.updated.asc(), entry.id.asc());
|
||||||
} else {
|
} else {
|
||||||
criteria.addOrder(Order.desc(entry.updated.getMetadata().getName())).addOrder(Order.desc(entry.id.getMetadata().getName()));
|
query.orderBy(entry.updated.desc(), entry.id.desc());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (offset > -1) {
|
if (offset > -1) {
|
||||||
criteria.setFirstResult(offset);
|
query.offset(offset);
|
||||||
}
|
}
|
||||||
if (limit > -1) {
|
if (limit > -1) {
|
||||||
criteria.setMaxResults(limit);
|
query.limit(limit);
|
||||||
}
|
}
|
||||||
int timeout = config.getApplicationSettings().getQueryTimeout();
|
int timeout = config.getApplicationSettings().getQueryTimeout();
|
||||||
if (timeout > 0) {
|
if (timeout > 0) {
|
||||||
// hibernate timeout is in seconds, jpa timeout is in millis
|
query.setTimeout(timeout / 1000);
|
||||||
criteria.setTimeout(timeout / 1000);
|
|
||||||
}
|
}
|
||||||
return criteria;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
public List<FeedEntryStatus> findBySubscriptions(User user, List<FeedSubscription> subs, boolean unreadOnly,
|
||||||
public List<FeedEntryStatus> findBySubscriptions(User user, List<FeedSubscription> subs, boolean unreadOnly, String keywords,
|
List<FeedEntryKeyword> keywords, Date newerThan, int offset, int limit, ReadingOrder order, boolean includeContent,
|
||||||
Date newerThan, int offset, int limit, ReadingOrder order, boolean includeContent, boolean onlyIds, String tag) {
|
boolean onlyIds, String tag) {
|
||||||
int capacity = offset + limit;
|
int capacity = offset + limit;
|
||||||
Comparator<FeedEntryStatus> comparator = order == ReadingOrder.desc ? STATUS_COMPARATOR_DESC : STATUS_COMPARATOR_ASC;
|
Comparator<FeedEntryStatus> comparator = order == ReadingOrder.desc ? STATUS_COMPARATOR_DESC : STATUS_COMPARATOR_ASC;
|
||||||
FixedSizeSortedSet<FeedEntryStatus> set = new FixedSizeSortedSet<FeedEntryStatus>(capacity, comparator);
|
FixedSizeSortedSet<FeedEntryStatus> set = new FixedSizeSortedSet<FeedEntryStatus>(capacity, comparator);
|
||||||
for (FeedSubscription sub : subs) {
|
for (FeedSubscription sub : subs) {
|
||||||
Date last = (order != null && set.isFull()) ? set.last().getEntryUpdated() : null;
|
Date last = (order != null && set.isFull()) ? set.last().getEntryUpdated() : null;
|
||||||
Criteria criteria = buildSearchCriteria(user, sub, unreadOnly, keywords, newerThan, -1, capacity, order, last, tag);
|
HibernateQuery<FeedEntry> query = buildQuery(user, sub, unreadOnly, keywords, newerThan, -1, capacity, order, last, tag);
|
||||||
ProjectionList projection = Projections.projectionList();
|
List<Tuple> tuples = query.select(entry.id, entry.updated, status.id).fetch();
|
||||||
projection.add(Projections.property("id"), "id");
|
for (Tuple tuple : tuples) {
|
||||||
projection.add(Projections.property("updated"), "updated");
|
Long id = tuple.get(entry.id);
|
||||||
projection.add(Projections.property(ALIAS_STATUS + ".id"), "status_id");
|
Date updated = tuple.get(entry.updated);
|
||||||
criteria.setProjection(projection);
|
Long statusId = tuple.get(status.id);
|
||||||
criteria.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
|
|
||||||
List<Map<String, Object>> list = criteria.list();
|
|
||||||
for (Map<String, Object> map : list) {
|
|
||||||
Long id = (Long) map.get("id");
|
|
||||||
Date updated = (Date) map.get("updated");
|
|
||||||
Long statusId = (Long) map.get("status_id");
|
|
||||||
|
|
||||||
FeedEntry entry = new FeedEntry();
|
FeedEntry entry = new FeedEntry();
|
||||||
entry.setId(id);
|
entry.setId(id);
|
||||||
@@ -231,7 +221,7 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
|||||||
List<FeedEntryStatus> placeholders = set.asList();
|
List<FeedEntryStatus> placeholders = set.asList();
|
||||||
int size = placeholders.size();
|
int size = placeholders.size();
|
||||||
if (size < offset) {
|
if (size < offset) {
|
||||||
return Lists.newArrayList();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
placeholders = placeholders.subList(Math.max(offset, 0), size);
|
placeholders = placeholders.subList(Math.max(offset, 0), size);
|
||||||
|
|
||||||
@@ -239,7 +229,7 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
|||||||
if (onlyIds) {
|
if (onlyIds) {
|
||||||
statuses = placeholders;
|
statuses = placeholders;
|
||||||
} else {
|
} else {
|
||||||
statuses = Lists.newArrayList();
|
statuses = new ArrayList<>();
|
||||||
for (FeedEntryStatus placeholder : placeholders) {
|
for (FeedEntryStatus placeholder : placeholders) {
|
||||||
Long statusId = placeholder.getId();
|
Long statusId = placeholder.getId();
|
||||||
FeedEntry entry = feedEntryDAO.findById(placeholder.getEntry().getId());
|
FeedEntry entry = feedEntryDAO.findById(placeholder.getEntry().getId());
|
||||||
@@ -253,19 +243,13 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
|||||||
return statuses;
|
return statuses;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public UnreadCount getUnreadCount(User user, FeedSubscription subscription) {
|
public UnreadCount getUnreadCount(User user, FeedSubscription subscription) {
|
||||||
UnreadCount uc = null;
|
UnreadCount uc = null;
|
||||||
Criteria criteria = buildSearchCriteria(user, subscription, true, null, null, -1, -1, null, null, null);
|
HibernateQuery<FeedEntry> query = buildQuery(user, subscription, true, null, null, -1, -1, null, null, null);
|
||||||
ProjectionList projection = Projections.projectionList();
|
List<Tuple> tuples = query.select(entry.count(), entry.updated.max()).fetch();
|
||||||
projection.add(Projections.rowCount(), "count");
|
for (Tuple tuple : tuples) {
|
||||||
projection.add(Projections.max(QFeedEntry.feedEntry.updated.getMetadata().getName()), "updated");
|
Long count = tuple.get(entry.count());
|
||||||
criteria.setProjection(projection);
|
Date updated = tuple.get(entry.updated.max());
|
||||||
criteria.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
|
|
||||||
List<Map<String, Object>> list = criteria.list();
|
|
||||||
for (Map<String, Object> row : list) {
|
|
||||||
Long count = (Long) row.get("count");
|
|
||||||
Date updated = (Date) row.get("updated");
|
|
||||||
uc = new UnreadCount(subscription.getId(), count, updated);
|
uc = new UnreadCount(subscription.getId(), count, updated);
|
||||||
}
|
}
|
||||||
return uc;
|
return uc;
|
||||||
@@ -282,7 +266,7 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<FeedEntryStatus> getOldStatuses(Date olderThan, int limit) {
|
public List<FeedEntryStatus> getOldStatuses(Date olderThan, int limit) {
|
||||||
return newQuery().from(status).where(status.entryInserted.lt(olderThan), status.starred.isFalse()).limit(limit).list(status);
|
return query().selectFrom(status).where(status.entryInserted.lt(olderThan), status.starred.isFalse()).limit(limit).fetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,27 +2,31 @@ package com.commafeed.backend.dao;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
|
|
||||||
import com.commafeed.backend.model.FeedEntry;
|
import com.commafeed.backend.model.FeedEntry;
|
||||||
import com.commafeed.backend.model.FeedEntryTag;
|
import com.commafeed.backend.model.FeedEntryTag;
|
||||||
import com.commafeed.backend.model.QFeedEntryTag;
|
import com.commafeed.backend.model.QFeedEntryTag;
|
||||||
import com.commafeed.backend.model.User;
|
import com.commafeed.backend.model.User;
|
||||||
import com.mysema.query.types.ConstructorExpression;
|
|
||||||
|
|
||||||
|
@Singleton
|
||||||
public class FeedEntryTagDAO extends GenericDAO<FeedEntryTag> {
|
public class FeedEntryTagDAO extends GenericDAO<FeedEntryTag> {
|
||||||
|
|
||||||
private QFeedEntryTag tag = QFeedEntryTag.feedEntryTag;
|
private QFeedEntryTag tag = QFeedEntryTag.feedEntryTag;
|
||||||
|
|
||||||
|
@Inject
|
||||||
public FeedEntryTagDAO(SessionFactory sessionFactory) {
|
public FeedEntryTagDAO(SessionFactory sessionFactory) {
|
||||||
super(sessionFactory);
|
super(sessionFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> findByUser(User user) {
|
public List<String> findByUser(User user) {
|
||||||
return newQuery().from(tag).where(tag.user.eq(user)).distinct().list(ConstructorExpression.create(String.class, tag.name));
|
return query().selectDistinct(tag.name).from(tag).where(tag.user.eq(user)).fetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<FeedEntryTag> findByEntry(User user, FeedEntry entry) {
|
public List<FeedEntryTag> findByEntry(User user, FeedEntry entry) {
|
||||||
return newQuery().from(tag).where(tag.user.eq(user), tag.entry.eq(entry)).list(tag);
|
return query().selectFrom(tag).where(tag.user.eq(user), tag.entry.eq(entry)).fetch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
package com.commafeed.backend.dao;
|
package com.commafeed.backend.dao;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
|
|
||||||
@@ -10,71 +15,58 @@ import com.commafeed.backend.model.FeedSubscription;
|
|||||||
import com.commafeed.backend.model.Models;
|
import com.commafeed.backend.model.Models;
|
||||||
import com.commafeed.backend.model.QFeedSubscription;
|
import com.commafeed.backend.model.QFeedSubscription;
|
||||||
import com.commafeed.backend.model.User;
|
import com.commafeed.backend.model.User;
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.querydsl.jpa.hibernate.HibernateQuery;
|
||||||
import com.mysema.query.jpa.hibernate.HibernateQuery;
|
|
||||||
|
|
||||||
|
@Singleton
|
||||||
public class FeedSubscriptionDAO extends GenericDAO<FeedSubscription> {
|
public class FeedSubscriptionDAO extends GenericDAO<FeedSubscription> {
|
||||||
|
|
||||||
private QFeedSubscription sub = QFeedSubscription.feedSubscription;
|
private QFeedSubscription sub = QFeedSubscription.feedSubscription;
|
||||||
|
|
||||||
|
@Inject
|
||||||
public FeedSubscriptionDAO(SessionFactory sessionFactory) {
|
public FeedSubscriptionDAO(SessionFactory sessionFactory) {
|
||||||
super(sessionFactory);
|
super(sessionFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FeedSubscription findById(User user, Long id) {
|
public FeedSubscription findById(User user, Long id) {
|
||||||
List<FeedSubscription> subs = newQuery().from(sub).where(sub.user.eq(user), sub.id.eq(id)).leftJoin(sub.feed).fetch()
|
List<FeedSubscription> subs = query().selectFrom(sub).where(sub.user.eq(user), sub.id.eq(id)).leftJoin(sub.feed).fetchJoin()
|
||||||
.leftJoin(sub.category).fetch().list(sub);
|
.leftJoin(sub.category).fetchJoin().fetch();
|
||||||
return initRelations(Iterables.getFirst(subs, null));
|
return initRelations(Iterables.getFirst(subs, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<FeedSubscription> findByFeed(Feed feed) {
|
public List<FeedSubscription> findByFeed(Feed feed) {
|
||||||
return newQuery().from(sub).where(sub.feed.eq(feed)).list(sub);
|
return query().selectFrom(sub).where(sub.feed.eq(feed)).fetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
public FeedSubscription findByFeed(User user, Feed feed) {
|
public FeedSubscription findByFeed(User user, Feed feed) {
|
||||||
List<FeedSubscription> subs = newQuery().from(sub).where(sub.user.eq(user), sub.feed.eq(feed)).list(sub);
|
List<FeedSubscription> subs = query().selectFrom(sub).where(sub.user.eq(user), sub.feed.eq(feed)).fetch();
|
||||||
return initRelations(Iterables.getFirst(subs, null));
|
return initRelations(Iterables.getFirst(subs, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<FeedSubscription> findAll(User user) {
|
public List<FeedSubscription> findAll(User user) {
|
||||||
List<FeedSubscription> subs = newQuery().from(sub).where(sub.user.eq(user)).leftJoin(sub.feed).fetch().leftJoin(sub.category)
|
List<FeedSubscription> subs = query().selectFrom(sub).where(sub.user.eq(user)).leftJoin(sub.feed).fetchJoin()
|
||||||
.fetch().list(sub);
|
.leftJoin(sub.category).fetchJoin().fetch();
|
||||||
return initRelations(subs);
|
return initRelations(subs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<FeedSubscription> findByCategory(User user, FeedCategory category) {
|
public List<FeedSubscription> findByCategory(User user, FeedCategory category) {
|
||||||
HibernateQuery query = newQuery().from(sub).where(sub.user.eq(user));
|
HibernateQuery<FeedSubscription> query = query().selectFrom(sub).where(sub.user.eq(user));
|
||||||
if (category == null) {
|
if (category == null) {
|
||||||
query.where(sub.category.isNull());
|
query.where(sub.category.isNull());
|
||||||
} else {
|
} else {
|
||||||
query.where(sub.category.eq(category));
|
query.where(sub.category.eq(category));
|
||||||
}
|
}
|
||||||
return initRelations(query.list(sub));
|
return initRelations(query.fetch());
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<FeedSubscription> findByCategories(User user, List<FeedCategory> categories) {
|
public List<FeedSubscription> findByCategories(User user, List<FeedCategory> categories) {
|
||||||
List<Long> categoryIds = Lists.transform(categories, new Function<FeedCategory, Long>() {
|
Set<Long> categoryIds = categories.stream().map(c -> c.getId()).collect(Collectors.toSet());
|
||||||
@Override
|
return findAll(user).stream().filter(s -> s.getCategory() != null && categoryIds.contains(s.getCategory().getId()))
|
||||||
public Long apply(FeedCategory input) {
|
.collect(Collectors.toList());
|
||||||
return input.getId();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
List<FeedSubscription> subscriptions = Lists.newArrayList();
|
|
||||||
for (FeedSubscription sub : findAll(user)) {
|
|
||||||
if (sub.getCategory() != null && categoryIds.contains(sub.getCategory().getId())) {
|
|
||||||
subscriptions.add(sub);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return subscriptions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<FeedSubscription> initRelations(List<FeedSubscription> list) {
|
private List<FeedSubscription> initRelations(List<FeedSubscription> list) {
|
||||||
for (FeedSubscription sub : list) {
|
list.forEach(s -> initRelations(s));
|
||||||
initRelations(sub);
|
|
||||||
}
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,25 @@
|
|||||||
package com.commafeed.backend.dao;
|
package com.commafeed.backend.dao;
|
||||||
|
|
||||||
import io.dropwizard.hibernate.AbstractDAO;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
|
|
||||||
import com.commafeed.backend.model.AbstractModel;
|
import com.commafeed.backend.model.AbstractModel;
|
||||||
import com.mysema.query.jpa.hibernate.HibernateQuery;
|
import com.querydsl.jpa.hibernate.HibernateQueryFactory;
|
||||||
|
|
||||||
|
import io.dropwizard.hibernate.AbstractDAO;
|
||||||
|
|
||||||
public abstract class GenericDAO<T extends AbstractModel> extends AbstractDAO<T> {
|
public abstract class GenericDAO<T extends AbstractModel> extends AbstractDAO<T> {
|
||||||
|
|
||||||
public GenericDAO(SessionFactory sessionFactory) {
|
private HibernateQueryFactory factory;
|
||||||
|
|
||||||
|
protected GenericDAO(SessionFactory sessionFactory) {
|
||||||
super(sessionFactory);
|
super(sessionFactory);
|
||||||
|
this.factory = new HibernateQueryFactory(() -> currentSession());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected HibernateQuery newQuery() {
|
protected HibernateQueryFactory query() {
|
||||||
return new HibernateQuery(currentSession());
|
return factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveOrUpdate(T model) {
|
public void saveOrUpdate(T model) {
|
||||||
@@ -24,19 +27,7 @@ public abstract class GenericDAO<T extends AbstractModel> extends AbstractDAO<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void saveOrUpdate(Collection<T> models) {
|
public void saveOrUpdate(Collection<T> models) {
|
||||||
for (T model : models) {
|
models.forEach(m -> persist(m));
|
||||||
persist(model);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void merge(T model) {
|
|
||||||
currentSession().merge(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void merge(Collection<T> models) {
|
|
||||||
for (T model : models) {
|
|
||||||
merge(model);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public T findById(Long id) {
|
public T findById(Long id) {
|
||||||
@@ -50,15 +41,8 @@ public abstract class GenericDAO<T extends AbstractModel> extends AbstractDAO<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int delete(Collection<T> objects) {
|
public int delete(Collection<T> objects) {
|
||||||
for (T object : objects) {
|
objects.forEach(o -> delete(o));
|
||||||
delete(object);
|
|
||||||
}
|
|
||||||
return objects.size();
|
return objects.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setTimeout(javax.persistence.Query query, int queryTimeout) {
|
|
||||||
if (queryTimeout > 0) {
|
|
||||||
query.setHint("javax.persistence.query.timeout", queryTimeout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,17 +5,26 @@ import org.hibernate.SessionFactory;
|
|||||||
import org.hibernate.Transaction;
|
import org.hibernate.Transaction;
|
||||||
import org.hibernate.context.internal.ManagedSessionContext;
|
import org.hibernate.context.internal.ManagedSessionContext;
|
||||||
|
|
||||||
public abstract class UnitOfWork<T> {
|
public class UnitOfWork {
|
||||||
|
|
||||||
private SessionFactory sessionFactory;
|
@FunctionalInterface
|
||||||
|
public static interface SessionRunner {
|
||||||
public UnitOfWork(SessionFactory sessionFactory) {
|
public void runInSession();
|
||||||
this.sessionFactory = sessionFactory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract T runInSession() throws Exception;
|
@FunctionalInterface
|
||||||
|
public static interface SessionRunnerReturningValue<T> {
|
||||||
|
public T runInSession();
|
||||||
|
}
|
||||||
|
|
||||||
public T run() {
|
public static void run(SessionFactory sessionFactory, SessionRunner sessionRunner) {
|
||||||
|
call(sessionFactory, () -> {
|
||||||
|
sessionRunner.runInSession();
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T call(SessionFactory sessionFactory, SessionRunnerReturningValue<T> sessionRunner) {
|
||||||
final Session session = sessionFactory.openSession();
|
final Session session = sessionFactory.openSession();
|
||||||
if (ManagedSessionContext.hasBind(sessionFactory)) {
|
if (ManagedSessionContext.hasBind(sessionFactory)) {
|
||||||
throw new IllegalStateException("Already in a unit of work!");
|
throw new IllegalStateException("Already in a unit of work!");
|
||||||
@@ -25,11 +34,11 @@ public abstract class UnitOfWork<T> {
|
|||||||
ManagedSessionContext.bind(session);
|
ManagedSessionContext.bind(session);
|
||||||
session.beginTransaction();
|
session.beginTransaction();
|
||||||
try {
|
try {
|
||||||
t = runInSession();
|
t = sessionRunner.runInSession();
|
||||||
commitTransaction(session);
|
commitTransaction(session);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
rollbackTransaction(session);
|
rollbackTransaction(session);
|
||||||
this.<RuntimeException> rethrow(e);
|
UnitOfWork.<RuntimeException> rethrow(e);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
session.close();
|
session.close();
|
||||||
@@ -38,14 +47,14 @@ public abstract class UnitOfWork<T> {
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void rollbackTransaction(Session session) {
|
private static void rollbackTransaction(Session session) {
|
||||||
final Transaction txn = session.getTransaction();
|
final Transaction txn = session.getTransaction();
|
||||||
if (txn != null && txn.isActive()) {
|
if (txn != null && txn.isActive()) {
|
||||||
txn.rollback();
|
txn.rollback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void commitTransaction(Session session) {
|
private static void commitTransaction(Session session) {
|
||||||
final Transaction txn = session.getTransaction();
|
final Transaction txn = session.getTransaction();
|
||||||
if (txn != null && txn.isActive()) {
|
if (txn != null && txn.isActive()) {
|
||||||
txn.commit();
|
txn.commit();
|
||||||
@@ -53,7 +62,7 @@ public abstract class UnitOfWork<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private <E extends Exception> void rethrow(Exception e) throws E {
|
private static <E extends Exception> void rethrow(Exception e) throws E {
|
||||||
throw (E) e;
|
throw (E) e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,35 +1,36 @@
|
|||||||
package com.commafeed.backend.dao;
|
package com.commafeed.backend.dao;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
|
|
||||||
import com.commafeed.backend.model.QUser;
|
import com.commafeed.backend.model.QUser;
|
||||||
import com.commafeed.backend.model.QUserRole;
|
|
||||||
import com.commafeed.backend.model.User;
|
import com.commafeed.backend.model.User;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
public class UserDAO extends GenericDAO<User> {
|
public class UserDAO extends GenericDAO<User> {
|
||||||
|
|
||||||
private QUser user = QUser.user;
|
private QUser user = QUser.user;
|
||||||
|
|
||||||
|
@Inject
|
||||||
public UserDAO(SessionFactory sessionFactory) {
|
public UserDAO(SessionFactory sessionFactory) {
|
||||||
super(sessionFactory);
|
super(sessionFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
public User findByName(String name) {
|
public User findByName(String name) {
|
||||||
return newQuery().from(user).where(user.name.equalsIgnoreCase(name)).leftJoin(user.roles, QUserRole.userRole).fetch()
|
return query().selectFrom(user).where(user.name.equalsIgnoreCase(name)).fetchOne();
|
||||||
.uniqueResult(user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public User findByApiKey(String key) {
|
public User findByApiKey(String key) {
|
||||||
return newQuery().from(user).where(user.apiKey.equalsIgnoreCase(key)).leftJoin(user.roles, QUserRole.userRole).fetch()
|
return query().selectFrom(user).where(user.apiKey.equalsIgnoreCase(key)).fetchOne();
|
||||||
.uniqueResult(user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public User findByEmail(String email) {
|
public User findByEmail(String email) {
|
||||||
return newQuery().from(user).where(user.email.equalsIgnoreCase(email)).leftJoin(user.roles, QUserRole.userRole).fetch()
|
return query().selectFrom(user).where(user.email.equalsIgnoreCase(email)).fetchOne();
|
||||||
.uniqueResult(user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public long count() {
|
public long count() {
|
||||||
return newQuery().from(user).count();
|
return query().selectFrom(user).fetchCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,10 @@ package com.commafeed.backend.dao;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
|
|
||||||
@@ -9,29 +13,26 @@ import com.commafeed.backend.model.QUserRole;
|
|||||||
import com.commafeed.backend.model.User;
|
import com.commafeed.backend.model.User;
|
||||||
import com.commafeed.backend.model.UserRole;
|
import com.commafeed.backend.model.UserRole;
|
||||||
import com.commafeed.backend.model.UserRole.Role;
|
import com.commafeed.backend.model.UserRole.Role;
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
|
|
||||||
|
@Singleton
|
||||||
public class UserRoleDAO extends GenericDAO<UserRole> {
|
public class UserRoleDAO extends GenericDAO<UserRole> {
|
||||||
|
|
||||||
private QUserRole role = QUserRole.userRole;
|
private QUserRole role = QUserRole.userRole;
|
||||||
|
|
||||||
|
@Inject
|
||||||
public UserRoleDAO(SessionFactory sessionFactory) {
|
public UserRoleDAO(SessionFactory sessionFactory) {
|
||||||
super(sessionFactory);
|
super(sessionFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<UserRole> findAll() {
|
public List<UserRole> findAll() {
|
||||||
return newQuery().from(role).leftJoin(role.user).fetch().distinct().list(role);
|
return query().selectFrom(role).leftJoin(role.user).fetchJoin().distinct().fetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<UserRole> findAll(User user) {
|
public List<UserRole> findAll(User user) {
|
||||||
return newQuery().from(role).where(role.user.eq(user)).distinct().list(role);
|
return query().selectFrom(role).where(role.user.eq(user)).distinct().fetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Role> findRoles(User user) {
|
public Set<Role> findRoles(User user) {
|
||||||
Set<Role> list = Sets.newHashSet();
|
return findAll(user).stream().map(r -> r.getRole()).collect(Collectors.toSet());
|
||||||
for (UserRole role : findAll(user)) {
|
|
||||||
list.add(role.getRole());
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,25 @@
|
|||||||
package com.commafeed.backend.dao;
|
package com.commafeed.backend.dao;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
|
|
||||||
import com.commafeed.backend.model.QUserSettings;
|
import com.commafeed.backend.model.QUserSettings;
|
||||||
import com.commafeed.backend.model.User;
|
import com.commafeed.backend.model.User;
|
||||||
import com.commafeed.backend.model.UserSettings;
|
import com.commafeed.backend.model.UserSettings;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
public class UserSettingsDAO extends GenericDAO<UserSettings> {
|
public class UserSettingsDAO extends GenericDAO<UserSettings> {
|
||||||
|
|
||||||
private QUserSettings settings = QUserSettings.userSettings;
|
private QUserSettings settings = QUserSettings.userSettings;
|
||||||
|
|
||||||
|
@Inject
|
||||||
public UserSettingsDAO(SessionFactory sessionFactory) {
|
public UserSettingsDAO(SessionFactory sessionFactory) {
|
||||||
super(sessionFactory);
|
super(sessionFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserSettings findByUser(User user) {
|
public UserSettings findByUser(User user) {
|
||||||
return newQuery().from(settings).where(settings.user.eq(user)).uniqueResult(settings);
|
return query().selectFrom(settings).where(settings.user.eq(user)).fetchFirst();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package com.commafeed.backend.favicon;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import com.commafeed.backend.model.Feed;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public abstract class AbstractFaviconFetcher {
|
||||||
|
|
||||||
|
private static List<String> ICON_MIMETYPE_BLACKLIST = Arrays.asList("application/xml", "text/html");
|
||||||
|
private static long MIN_ICON_LENGTH = 100;
|
||||||
|
private static long MAX_ICON_LENGTH = 100000;
|
||||||
|
|
||||||
|
protected static int TIMEOUT = 4000;
|
||||||
|
|
||||||
|
public abstract Favicon fetch(Feed feed);
|
||||||
|
|
||||||
|
protected boolean isValidIconResponse(byte[] content, String contentType) {
|
||||||
|
if (content == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
long length = content.length;
|
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(contentType)) {
|
||||||
|
contentType = contentType.split(";")[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ICON_MIMETYPE_BLACKLIST.contains(contentType)) {
|
||||||
|
log.debug("Content-Type {} is blacklisted", contentType);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length < MIN_ICON_LENGTH) {
|
||||||
|
log.debug("Length {} below MIN_ICON_LENGTH {}", length, MIN_ICON_LENGTH);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length > MAX_ICON_LENGTH) {
|
||||||
|
log.debug("Length {} greater than MAX_ICON_LENGTH {}", length, MAX_ICON_LENGTH);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public static class Favicon {
|
||||||
|
private final byte[] icon;
|
||||||
|
private final String mediaType;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,156 +1,132 @@
|
|||||||
package com.commafeed.backend.feed;
|
package com.commafeed.backend.favicon;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import javax.inject.Inject;
|
||||||
import java.util.List;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.jsoup.Jsoup;
|
import org.jsoup.Jsoup;
|
||||||
import org.jsoup.nodes.Document;
|
import org.jsoup.nodes.Document;
|
||||||
import org.jsoup.select.Elements;
|
import org.jsoup.select.Elements;
|
||||||
|
|
||||||
import com.commafeed.backend.HttpGetter;
|
import com.commafeed.backend.HttpGetter;
|
||||||
import com.commafeed.backend.HttpGetter.HttpResult;
|
import com.commafeed.backend.HttpGetter.HttpResult;
|
||||||
|
import com.commafeed.backend.feed.FeedUtils;
|
||||||
/**
|
import com.commafeed.backend.model.Feed;
|
||||||
* Inspired/Ported from https://github.com/potatolondon/getfavicon
|
|
||||||
*
|
/**
|
||||||
*/
|
* Inspired/Ported from https://github.com/potatolondon/getfavicon
|
||||||
@Slf4j
|
*
|
||||||
@AllArgsConstructor
|
*/
|
||||||
public class FaviconFetcher {
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
|
||||||
private static long MIN_ICON_LENGTH = 100;
|
@Singleton
|
||||||
private static long MAX_ICON_LENGTH = 100000;
|
public class DefaultFaviconFetcher extends AbstractFaviconFetcher {
|
||||||
private static int TIMEOUT = 4000;
|
|
||||||
|
private final HttpGetter getter;
|
||||||
protected static List<String> ICON_MIMETYPES = Arrays.asList("image/x-icon", "image/vnd.microsoft.icon", "image/ico", "image/icon",
|
|
||||||
"text/ico", "application/ico", "image/x-ms-bmp", "image/x-bmp", "image/gif", "image/png", "image/jpeg");
|
@Override
|
||||||
private static List<String> ICON_MIMETYPE_BLACKLIST = Arrays.asList("application/xml", "text/html");
|
public Favicon fetch(Feed feed) {
|
||||||
|
Favicon icon = fetch(feed.getLink());
|
||||||
private final HttpGetter getter;
|
if (icon == null) {
|
||||||
|
icon = fetch(feed.getUrl());
|
||||||
public byte[] fetch(String url) {
|
}
|
||||||
|
return icon;
|
||||||
if (url == null) {
|
}
|
||||||
log.debug("url is null");
|
|
||||||
return null;
|
private Favicon fetch(String url) {
|
||||||
}
|
if (url == null) {
|
||||||
|
log.debug("url is null");
|
||||||
int doubleSlash = url.indexOf("//");
|
return null;
|
||||||
if (doubleSlash == -1) {
|
}
|
||||||
doubleSlash = 0;
|
|
||||||
} else {
|
int doubleSlash = url.indexOf("//");
|
||||||
doubleSlash += 2;
|
if (doubleSlash == -1) {
|
||||||
}
|
doubleSlash = 0;
|
||||||
int firstSlash = url.indexOf('/', doubleSlash);
|
} else {
|
||||||
if (firstSlash != -1) {
|
doubleSlash += 2;
|
||||||
url = url.substring(0, firstSlash);
|
}
|
||||||
}
|
int firstSlash = url.indexOf('/', doubleSlash);
|
||||||
|
if (firstSlash != -1) {
|
||||||
byte[] icon = getIconAtRoot(url);
|
url = url.substring(0, firstSlash);
|
||||||
|
}
|
||||||
if (icon == null) {
|
|
||||||
icon = getIconInPage(url);
|
Favicon icon = getIconAtRoot(url);
|
||||||
}
|
|
||||||
|
if (icon == null) {
|
||||||
return icon;
|
icon = getIconInPage(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] getIconAtRoot(String url) {
|
return icon;
|
||||||
byte[] bytes = null;
|
}
|
||||||
String contentType = null;
|
|
||||||
|
private Favicon getIconAtRoot(String url) {
|
||||||
try {
|
byte[] bytes = null;
|
||||||
url = FeedUtils.removeTrailingSlash(url) + "/favicon.ico";
|
String contentType = null;
|
||||||
log.debug("getting root icon at {}", url);
|
|
||||||
HttpResult result = getter.getBinary(url, TIMEOUT);
|
try {
|
||||||
bytes = result.getContent();
|
url = FeedUtils.removeTrailingSlash(url) + "/favicon.ico";
|
||||||
contentType = result.getContentType();
|
log.debug("getting root icon at {}", url);
|
||||||
} catch (Exception e) {
|
HttpResult result = getter.getBinary(url, TIMEOUT);
|
||||||
log.debug("Failed to retrieve iconAtRoot: " + e.getMessage(), e);
|
bytes = result.getContent();
|
||||||
}
|
contentType = result.getContentType();
|
||||||
|
} catch (Exception e) {
|
||||||
if (!isValidIconResponse(bytes, contentType)) {
|
log.debug("Failed to retrieve iconAtRoot for url {}: ", url);
|
||||||
bytes = null;
|
log.trace("Failed to retrieve iconAtRoot for url {}: ", url, e);
|
||||||
}
|
}
|
||||||
return bytes;
|
|
||||||
}
|
if (!isValidIconResponse(bytes, contentType)) {
|
||||||
|
return null;
|
||||||
private boolean isValidIconResponse(byte[] content, String contentType) {
|
}
|
||||||
if (content == null) {
|
return new Favicon(bytes, contentType);
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
private Favicon getIconInPage(String url) {
|
||||||
long length = content.length;
|
|
||||||
|
Document doc = null;
|
||||||
if (StringUtils.isNotBlank(contentType)) {
|
try {
|
||||||
contentType = contentType.split(";")[0];
|
HttpResult result = getter.getBinary(url, TIMEOUT);
|
||||||
}
|
doc = Jsoup.parse(new String(result.getContent()), url);
|
||||||
|
} catch (Exception e) {
|
||||||
if (ICON_MIMETYPE_BLACKLIST.contains(contentType)) {
|
log.debug("Failed to retrieve page to find icon");
|
||||||
log.debug("Content-Type {} is blacklisted", contentType);
|
log.trace("Failed to retrieve page to find icon", e);
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (length < MIN_ICON_LENGTH) {
|
Elements icons = doc.select("link[rel~=(?i)^(shortcut|icon|shortcut icon)$]");
|
||||||
log.debug("Length {} below MIN_ICON_LENGTH {}", length, MIN_ICON_LENGTH);
|
|
||||||
return false;
|
if (icons.isEmpty()) {
|
||||||
}
|
log.debug("No icon found in page {}", url);
|
||||||
|
return null;
|
||||||
if (length > MAX_ICON_LENGTH) {
|
}
|
||||||
log.debug("Length {} greater than MAX_ICON_LENGTH {}", length, MAX_ICON_LENGTH);
|
|
||||||
return false;
|
String href = icons.get(0).attr("abs:href");
|
||||||
}
|
if (StringUtils.isBlank(href)) {
|
||||||
|
log.debug("No icon found in page");
|
||||||
return true;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] getIconInPage(String url) {
|
log.debug("Found unconfirmed iconInPage at {}", href);
|
||||||
|
|
||||||
Document doc = null;
|
byte[] bytes = null;
|
||||||
try {
|
String contentType = null;
|
||||||
HttpResult result = getter.getBinary(url, TIMEOUT);
|
try {
|
||||||
doc = Jsoup.parse(new String(result.getContent()), url);
|
HttpResult result = getter.getBinary(href, TIMEOUT);
|
||||||
} catch (Exception e) {
|
bytes = result.getContent();
|
||||||
log.debug("Failed to retrieve page to find icon");
|
contentType = result.getContentType();
|
||||||
return null;
|
} catch (Exception e) {
|
||||||
}
|
log.debug("Failed to retrieve icon found in page {}", href);
|
||||||
|
log.trace("Failed to retrieve icon found in page {}", href, e);
|
||||||
Elements icons = doc.select("link[rel~=(?i)^(shortcut|icon|shortcut icon)$]");
|
return null;
|
||||||
|
}
|
||||||
if (icons.isEmpty()) {
|
|
||||||
log.debug("No icon found in page {}", url);
|
if (!isValidIconResponse(bytes, contentType)) {
|
||||||
return null;
|
log.debug("Invalid icon found for {}", href);
|
||||||
}
|
return null;
|
||||||
|
}
|
||||||
String href = icons.get(0).attr("abs:href");
|
|
||||||
if (StringUtils.isBlank(href)) {
|
return new Favicon(bytes, contentType);
|
||||||
log.debug("No icon found in page");
|
}
|
||||||
return null;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
log.debug("Found unconfirmed iconInPage at {}", href);
|
|
||||||
|
|
||||||
byte[] bytes = null;
|
|
||||||
String contentType = null;
|
|
||||||
try {
|
|
||||||
HttpResult result = getter.getBinary(href, TIMEOUT);
|
|
||||||
bytes = result.getContent();
|
|
||||||
contentType = result.getContentType();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.debug("Failed to retrieve icon found in page {}", href);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isValidIconResponse(bytes, contentType)) {
|
|
||||||
log.debug("Invalid icon found for {}", href);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
package com.commafeed.backend.favicon;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import org.apache.http.NameValuePair;
|
||||||
|
import org.apache.http.client.utils.URLEncodedUtils;
|
||||||
|
|
||||||
|
import com.commafeed.backend.HttpGetter;
|
||||||
|
import com.commafeed.backend.HttpGetter.HttpResult;
|
||||||
|
import com.commafeed.backend.model.Feed;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
|
||||||
|
@Singleton
|
||||||
|
public class FacebookFaviconFetcher extends AbstractFaviconFetcher {
|
||||||
|
|
||||||
|
private final HttpGetter getter;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Favicon fetch(Feed feed) {
|
||||||
|
String url = feed.getUrl();
|
||||||
|
|
||||||
|
if (!url.toLowerCase().contains("www.facebook.com")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String userName = extractUserName(url);
|
||||||
|
if (userName == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String iconUrl = String.format("https://graph.facebook.com/%s/picture?type=square&height=16", userName);
|
||||||
|
|
||||||
|
byte[] bytes = null;
|
||||||
|
String contentType = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
log.debug("Getting Facebook user's icon, {}", url);
|
||||||
|
|
||||||
|
HttpResult iconResult = getter.getBinary(iconUrl, TIMEOUT);
|
||||||
|
bytes = iconResult.getContent();
|
||||||
|
contentType = iconResult.getContentType();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.debug("Failed to retrieve Facebook icon", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isValidIconResponse(bytes, contentType)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new Favicon(bytes, contentType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String extractUserName(String url) {
|
||||||
|
URI uri = null;
|
||||||
|
try {
|
||||||
|
uri = new URI(url);
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
log.debug("could not parse url", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<NameValuePair> params = URLEncodedUtils.parse(uri, StandardCharsets.UTF_8.name());
|
||||||
|
for (NameValuePair param : params) {
|
||||||
|
if ("id".equals(param.getName())) {
|
||||||
|
return param.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
package com.commafeed.backend.favicon;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.apache.http.NameValuePair;
|
||||||
|
import org.apache.http.client.utils.URLEncodedUtils;
|
||||||
|
|
||||||
|
import com.commafeed.CommaFeedConfiguration;
|
||||||
|
import com.commafeed.backend.HttpGetter;
|
||||||
|
import com.commafeed.backend.HttpGetter.HttpResult;
|
||||||
|
import com.commafeed.backend.model.Feed;
|
||||||
|
import com.google.api.client.http.HttpRequest;
|
||||||
|
import com.google.api.client.http.HttpRequestInitializer;
|
||||||
|
import com.google.api.client.http.javanet.NetHttpTransport;
|
||||||
|
import com.google.api.client.json.jackson2.JacksonFactory;
|
||||||
|
import com.google.api.services.youtube.YouTube;
|
||||||
|
import com.google.api.services.youtube.model.Channel;
|
||||||
|
import com.google.api.services.youtube.model.ChannelListResponse;
|
||||||
|
import com.google.api.services.youtube.model.Thumbnail;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor(onConstructor = @__({ @Inject }) )
|
||||||
|
@Singleton
|
||||||
|
public class YoutubeFaviconFetcher extends AbstractFaviconFetcher {
|
||||||
|
|
||||||
|
private final HttpGetter getter;
|
||||||
|
private final CommaFeedConfiguration config;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Favicon fetch(Feed feed) {
|
||||||
|
String url = feed.getUrl();
|
||||||
|
|
||||||
|
if (!url.toLowerCase().contains("youtube.com/feeds/videos.xml")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String googleAuthKey = config.getApplicationSettings().getGoogleAuthKey();
|
||||||
|
if (googleAuthKey == null) {
|
||||||
|
log.debug("no google auth key configured");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] bytes = null;
|
||||||
|
String contentType = null;
|
||||||
|
try {
|
||||||
|
List<NameValuePair> params = URLEncodedUtils.parse(url.substring(url.indexOf("?") + 1), StandardCharsets.UTF_8);
|
||||||
|
Optional<NameValuePair> userId = params.stream().filter(nvp -> nvp.getName().equalsIgnoreCase("user")).findFirst();
|
||||||
|
Optional<NameValuePair> channelId = params.stream().filter(nvp -> nvp.getName().equalsIgnoreCase("channel_id")).findFirst();
|
||||||
|
if (!userId.isPresent() && !channelId.isPresent()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
YouTube youtube = new YouTube.Builder(new NetHttpTransport(), JacksonFactory.getDefaultInstance(),
|
||||||
|
new HttpRequestInitializer() {
|
||||||
|
@Override
|
||||||
|
public void initialize(HttpRequest request) throws IOException {
|
||||||
|
}
|
||||||
|
}).setApplicationName("CommaFeed").build();
|
||||||
|
|
||||||
|
YouTube.Channels.List list = youtube.channels().list("snippet");
|
||||||
|
list.setKey(googleAuthKey);
|
||||||
|
if (userId.isPresent()) {
|
||||||
|
list.setForUsername(userId.get().getValue());
|
||||||
|
} else {
|
||||||
|
list.setId(channelId.get().getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("contacting youtube api");
|
||||||
|
ChannelListResponse response = list.execute();
|
||||||
|
if (response.getItems().isEmpty()) {
|
||||||
|
log.debug("youtube api returned no items");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Channel channel = response.getItems().get(0);
|
||||||
|
Thumbnail thumbnail = channel.getSnippet().getThumbnails().getDefault();
|
||||||
|
|
||||||
|
log.debug("fetching favicon");
|
||||||
|
HttpResult iconResult = getter.getBinary(thumbnail.getUrl(), TIMEOUT);
|
||||||
|
bytes = iconResult.getContent();
|
||||||
|
contentType = iconResult.getContentType();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.debug("Failed to retrieve YouTube icon", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isValidIconResponse(bytes, contentType)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new Favicon(bytes, contentType);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package com.commafeed.backend.feed;
|
||||||
|
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This code is copied and simplified from GWT
|
||||||
|
* https://github.com/google-web-toolkit/gwt/blob/master/user/src/com/google/gwt/i18n/shared/BidiUtils.java Released under Apache 2.0
|
||||||
|
* license, credit of it goes to Google and please use GWT wherever possible instead of this
|
||||||
|
*/
|
||||||
|
class EstimateDirection {
|
||||||
|
private static final float RTL_DETECTION_THRESHOLD = 0.40f;
|
||||||
|
|
||||||
|
private static final String LTR_CHARS = "A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02B8\u0300-\u0590\u0800-\u1FFF"
|
||||||
|
+ "\u2C00-\uFB1C\uFDFE-\uFE6F\uFEFD-\uFFFF";
|
||||||
|
private static final String RTL_CHARS = "\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC";
|
||||||
|
|
||||||
|
private static final Pattern WORD_SEPARATOR_RE = Pattern.compile("\\s+");
|
||||||
|
private static final Pattern FIRST_STRONG_IS_RTL_RE = Pattern.compile("^[^" + LTR_CHARS + "]*[" + RTL_CHARS + ']');
|
||||||
|
private static final Pattern IS_REQUIRED_LTR_RE = Pattern.compile("^http://.*");
|
||||||
|
private static final Pattern HAS_ANY_LTR_RE = Pattern.compile("[" + LTR_CHARS + ']');
|
||||||
|
|
||||||
|
private static boolean startsWithRtl(String str) {
|
||||||
|
return FIRST_STRONG_IS_RTL_RE.matcher(str).matches();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasAnyLtr(String str) {
|
||||||
|
return HAS_ANY_LTR_RE.matcher(str).matches();
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isRTL(String str) {
|
||||||
|
int rtlCount = 0;
|
||||||
|
int total = 0;
|
||||||
|
String[] tokens = WORD_SEPARATOR_RE.split(str, 20); // limit splits to 20, usually enough
|
||||||
|
for (int i = 0; i < tokens.length; i++) {
|
||||||
|
String token = tokens[i];
|
||||||
|
if (startsWithRtl(token)) {
|
||||||
|
rtlCount++;
|
||||||
|
total++;
|
||||||
|
} else if (IS_REQUIRED_LTR_RE.matcher(token).matches()) {
|
||||||
|
// do nothing
|
||||||
|
} else if (hasAnyLtr(token)) {
|
||||||
|
total++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return total == 0 ? false : ((float) rtlCount / total > RTL_DETECTION_THRESHOLD ? true : false);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.commafeed.backend.feed;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A keyword used in a search query
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class FeedEntryKeyword {
|
||||||
|
|
||||||
|
public static enum Mode {
|
||||||
|
INCLUDE, EXCLUDE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String keyword;
|
||||||
|
private final Mode mode;
|
||||||
|
|
||||||
|
public static List<FeedEntryKeyword> fromQueryString(String keywords) {
|
||||||
|
List<FeedEntryKeyword> list = new ArrayList<>();
|
||||||
|
if (keywords != null) {
|
||||||
|
for (String keyword : StringUtils.split(keywords)) {
|
||||||
|
boolean not = false;
|
||||||
|
if (keyword.startsWith("-") || keyword.startsWith("!")) {
|
||||||
|
not = true;
|
||||||
|
keyword = keyword.substring(1);
|
||||||
|
}
|
||||||
|
list.add(new FeedEntryKeyword(keyword, not ? Mode.EXCLUDE : Mode.INCLUDE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,10 @@ package com.commafeed.backend.feed;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.StringUtils;
|
import org.apache.commons.codec.binary.StringUtils;
|
||||||
@@ -17,10 +20,11 @@ import com.commafeed.backend.HttpGetter;
|
|||||||
import com.commafeed.backend.HttpGetter.HttpResult;
|
import com.commafeed.backend.HttpGetter.HttpResult;
|
||||||
import com.commafeed.backend.HttpGetter.NotModifiedException;
|
import com.commafeed.backend.HttpGetter.NotModifiedException;
|
||||||
import com.commafeed.backend.model.Feed;
|
import com.commafeed.backend.model.Feed;
|
||||||
import com.sun.syndication.io.FeedException;
|
import com.rometools.rome.io.FeedException;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@AllArgsConstructor
|
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
|
||||||
|
@Singleton
|
||||||
public class FeedFetcher {
|
public class FeedFetcher {
|
||||||
|
|
||||||
private final FeedParser parser;
|
private final FeedParser parser;
|
||||||
@@ -37,16 +41,16 @@ public class FeedFetcher {
|
|||||||
byte[] content = result.getContent();
|
byte[] content = result.getContent();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fetchedFeed = parser.parse(feedUrl, content);
|
fetchedFeed = parser.parse(result.getUrlAfterRedirect(), content);
|
||||||
} catch (FeedException e) {
|
} catch (FeedException e) {
|
||||||
if (extractFeedUrlFromHtml) {
|
if (extractFeedUrlFromHtml) {
|
||||||
String extractedUrl = extractFeedUrl(StringUtils.newStringUtf8(result.getContent()), feedUrl);
|
String extractedUrl = extractFeedUrl(StringUtils.newStringUtf8(result.getContent()), feedUrl);
|
||||||
if (org.apache.commons.lang.StringUtils.isNotBlank(extractedUrl)) {
|
if (org.apache.commons.lang3.StringUtils.isNotBlank(extractedUrl)) {
|
||||||
feedUrl = extractedUrl;
|
feedUrl = extractedUrl;
|
||||||
|
|
||||||
result = getter.getBinary(extractedUrl, lastModified, eTag, timeout);
|
result = getter.getBinary(extractedUrl, lastModified, eTag, timeout);
|
||||||
content = result.getContent();
|
content = result.getContent();
|
||||||
fetchedFeed = parser.parse(feedUrl, content);
|
fetchedFeed = parser.parse(result.getUrlAfterRedirect(), content);
|
||||||
} else {
|
} else {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
@@ -73,7 +77,7 @@ public class FeedFetcher {
|
|||||||
|
|
||||||
Feed feed = fetchedFeed.getFeed();
|
Feed feed = fetchedFeed.getFeed();
|
||||||
feed.setLastModifiedHeader(result.getLastModifiedSince());
|
feed.setLastModifiedHeader(result.getLastModifiedSince());
|
||||||
feed.setEtagHeader(FeedUtils.truncate(result.geteTag(), 255));
|
feed.setEtagHeader(FeedUtils.truncate(result.getETag(), 255));
|
||||||
feed.setLastContentHash(hash);
|
feed.setLastContentHash(hash);
|
||||||
fetchedFeed.setFetchDuration(result.getDuration());
|
fetchedFeed.setFetchDuration(result.getDuration());
|
||||||
fetchedFeed.setUrlAfterRedirect(result.getUrlAfterRedirect());
|
fetchedFeed.setUrlAfterRedirect(result.getUrlAfterRedirect());
|
||||||
@@ -89,9 +93,9 @@ public class FeedFetcher {
|
|||||||
Elements atom = doc.select("link[type=application/atom+xml]");
|
Elements atom = doc.select("link[type=application/atom+xml]");
|
||||||
Elements rss = doc.select("link[type=application/rss+xml]");
|
Elements rss = doc.select("link[type=application/rss+xml]");
|
||||||
if (!atom.isEmpty()) {
|
if (!atom.isEmpty()) {
|
||||||
foundUrl = atom.get(0).attr("abs:href").toString();
|
foundUrl = atom.get(0).attr("abs:href");
|
||||||
} else if (!rss.isEmpty()) {
|
} else if (!rss.isEmpty()) {
|
||||||
foundUrl = rss.get(0).attr("abs:href").toString();
|
foundUrl = rss.get(0).attr("abs:href");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return foundUrl;
|
return foundUrl;
|
||||||
|
|||||||
@@ -1,34 +1,38 @@
|
|||||||
package com.commafeed.backend.feed;
|
package com.commafeed.backend.feed;
|
||||||
|
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang.SystemUtils;
|
import org.jdom2.Element;
|
||||||
import org.jdom.Element;
|
import org.jdom2.Namespace;
|
||||||
import org.jdom.Namespace;
|
|
||||||
import org.xml.sax.InputSource;
|
import org.xml.sax.InputSource;
|
||||||
|
|
||||||
import com.commafeed.backend.model.Feed;
|
import com.commafeed.backend.model.Feed;
|
||||||
import com.commafeed.backend.model.FeedEntry;
|
import com.commafeed.backend.model.FeedEntry;
|
||||||
import com.commafeed.backend.model.FeedEntryContent;
|
import com.commafeed.backend.model.FeedEntryContent;
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.common.collect.Collections2;
|
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.sun.syndication.feed.synd.SyndContent;
|
import com.rometools.rome.feed.synd.SyndEnclosure;
|
||||||
import com.sun.syndication.feed.synd.SyndEnclosure;
|
import com.rometools.rome.feed.synd.SyndEntry;
|
||||||
import com.sun.syndication.feed.synd.SyndEntry;
|
import com.rometools.rome.feed.synd.SyndFeed;
|
||||||
import com.sun.syndication.feed.synd.SyndFeed;
|
import com.rometools.rome.feed.synd.SyndLink;
|
||||||
import com.sun.syndication.feed.synd.SyndLink;
|
import com.rometools.rome.feed.synd.SyndLinkImpl;
|
||||||
import com.sun.syndication.feed.synd.SyndLinkImpl;
|
import com.rometools.rome.io.FeedException;
|
||||||
import com.sun.syndication.io.FeedException;
|
import com.rometools.rome.io.SyndFeedInput;
|
||||||
import com.sun.syndication.io.SyndFeedInput;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
|
||||||
|
@Singleton
|
||||||
public class FeedParser {
|
public class FeedParser {
|
||||||
|
|
||||||
private static final String ATOM_10_URI = "http://www.w3.org/2005/Atom";
|
private static final String ATOM_10_URI = "http://www.w3.org/2005/Atom";
|
||||||
@@ -37,20 +41,13 @@ public class FeedParser {
|
|||||||
private static final Date START = new Date(86400000);
|
private static final Date START = new Date(86400000);
|
||||||
private static final Date END = new Date(1000l * Integer.MAX_VALUE - 86400000);
|
private static final Date END = new Date(1000l * Integer.MAX_VALUE - 86400000);
|
||||||
|
|
||||||
private static final Function<SyndContent, String> CONTENT_TO_STRING = new Function<SyndContent, String>() {
|
|
||||||
public String apply(SyndContent content) {
|
|
||||||
return content.getValue();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public FetchedFeed parse(String feedUrl, byte[] xml) throws FeedException {
|
public FetchedFeed parse(String feedUrl, byte[] xml) throws FeedException {
|
||||||
FetchedFeed fetchedFeed = new FetchedFeed();
|
FetchedFeed fetchedFeed = new FetchedFeed();
|
||||||
Feed feed = fetchedFeed.getFeed();
|
Feed feed = fetchedFeed.getFeed();
|
||||||
List<FeedEntry> entries = fetchedFeed.getEntries();
|
List<FeedEntry> entries = fetchedFeed.getEntries();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String encoding = FeedUtils.guessEncoding(xml);
|
Charset encoding = FeedUtils.guessEncoding(xml);
|
||||||
String xmlString = FeedUtils.trimInvalidXmlCharacters(new String(xml, encoding));
|
String xmlString = FeedUtils.trimInvalidXmlCharacters(new String(xml, encoding));
|
||||||
if (xmlString == null) {
|
if (xmlString == null) {
|
||||||
throw new FeedException("Input string is null for url " + feedUrl);
|
throw new FeedException("Input string is null for url " + feedUrl);
|
||||||
@@ -80,8 +77,8 @@ public class FeedParser {
|
|||||||
}
|
}
|
||||||
entry.setGuid(FeedUtils.truncate(guid, 2048));
|
entry.setGuid(FeedUtils.truncate(guid, 2048));
|
||||||
entry.setUpdated(validateDate(getEntryUpdateDate(item), true));
|
entry.setUpdated(validateDate(getEntryUpdateDate(item), true));
|
||||||
entry.setUrl(FeedUtils.truncate(FeedUtils.toAbsoluteUrl(item.getLink(), feed.getLink(), feed.getUrlAfterRedirect()), 2048));
|
entry.setUrl(FeedUtils.truncate(FeedUtils.toAbsoluteUrl(item.getLink(), feed.getLink(), feedUrl), 2048));
|
||||||
|
|
||||||
// if link is empty but guid is used as url
|
// if link is empty but guid is used as url
|
||||||
if (StringUtils.isBlank(entry.getUrl()) && StringUtils.startsWith(entry.getGuid(), "http")) {
|
if (StringUtils.isBlank(entry.getUrl()) && StringUtils.startsWith(entry.getGuid(), "http")) {
|
||||||
entry.setUrl(entry.getGuid());
|
entry.setUrl(entry.getGuid());
|
||||||
@@ -89,9 +86,11 @@ public class FeedParser {
|
|||||||
|
|
||||||
FeedEntryContent content = new FeedEntryContent();
|
FeedEntryContent content = new FeedEntryContent();
|
||||||
content.setContent(getContent(item));
|
content.setContent(getContent(item));
|
||||||
|
content.setCategories(FeedUtils.truncate(
|
||||||
|
item.getCategories().stream().map(c -> c.getName()).collect(Collectors.joining(", ")), 4096));
|
||||||
content.setTitle(getTitle(item));
|
content.setTitle(getTitle(item));
|
||||||
content.setAuthor(StringUtils.trimToNull(item.getAuthor()));
|
content.setAuthor(StringUtils.trimToNull(item.getAuthor()));
|
||||||
SyndEnclosure enclosure = (SyndEnclosure) Iterables.getFirst(item.getEnclosures(), null);
|
SyndEnclosure enclosure = Iterables.getFirst(item.getEnclosures(), null);
|
||||||
if (enclosure != null) {
|
if (enclosure != null) {
|
||||||
content.setEnclosureUrl(FeedUtils.truncate(enclosure.getUrl(), 2048));
|
content.setEnclosureUrl(FeedUtils.truncate(enclosure.getUrl(), 2048));
|
||||||
content.setEnclosureType(enclosure.getType());
|
content.setEnclosureType(enclosure.getType());
|
||||||
@@ -121,24 +120,17 @@ public class FeedParser {
|
|||||||
/**
|
/**
|
||||||
* Adds atom links for rss feeds
|
* Adds atom links for rss feeds
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
|
||||||
private void handleForeignMarkup(SyndFeed feed) {
|
private void handleForeignMarkup(SyndFeed feed) {
|
||||||
Object foreignMarkup = feed.getForeignMarkup();
|
List<Element> foreignMarkup = feed.getForeignMarkup();
|
||||||
if (foreignMarkup == null) {
|
if (foreignMarkup == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (foreignMarkup instanceof List) {
|
for (Element element : foreignMarkup) {
|
||||||
List elements = (List) foreignMarkup;
|
if ("link".equals(element.getName()) && ATOM_10_NS.equals(element.getNamespace())) {
|
||||||
for (Object object : elements) {
|
SyndLink link = new SyndLinkImpl();
|
||||||
if (object instanceof Element) {
|
link.setRel(element.getAttributeValue("rel"));
|
||||||
Element element = (Element) object;
|
link.setHref(element.getAttributeValue("href"));
|
||||||
if ("link".equals(element.getName()) && ATOM_10_NS.equals(element.getNamespace())) {
|
feed.getLinks().add(link);
|
||||||
SyndLink link = new SyndLinkImpl();
|
|
||||||
link.setRel(element.getAttributeValue("rel"));
|
|
||||||
link.setHref(element.getAttributeValue("href"));
|
|
||||||
feed.getLinks().add(link);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -169,13 +161,12 @@ public class FeedParser {
|
|||||||
return date;
|
return date;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private String getContent(SyndEntry item) {
|
private String getContent(SyndEntry item) {
|
||||||
String content = null;
|
String content = null;
|
||||||
if (item.getContents().isEmpty()) {
|
if (item.getContents().isEmpty()) {
|
||||||
content = item.getDescription() == null ? null : item.getDescription().getValue();
|
content = item.getDescription() == null ? null : item.getDescription().getValue();
|
||||||
} else {
|
} else {
|
||||||
content = StringUtils.join(Collections2.transform(item.getContents(), CONTENT_TO_STRING), SystemUtils.LINE_SEPARATOR);
|
content = item.getContents().stream().map(c -> c.getValue()).collect(Collectors.joining(System.lineSeparator()));
|
||||||
}
|
}
|
||||||
return StringUtils.trimToNull(content);
|
return StringUtils.trimToNull(content);
|
||||||
}
|
}
|
||||||
@@ -193,9 +184,8 @@ public class FeedParser {
|
|||||||
return StringUtils.trimToNull(title);
|
return StringUtils.trimToNull(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private String findHub(SyndFeed feed) {
|
private String findHub(SyndFeed feed) {
|
||||||
for (SyndLink l : (List<SyndLink>) feed.getLinks()) {
|
for (SyndLink l : feed.getLinks()) {
|
||||||
if ("hub".equalsIgnoreCase(l.getRel())) {
|
if ("hub".equalsIgnoreCase(l.getRel())) {
|
||||||
log.debug("found hub {} for feed {}", l.getHref(), feed.getLink());
|
log.debug("found hub {} for feed {}", l.getHref(), feed.getLink());
|
||||||
return l.getHref();
|
return l.getHref();
|
||||||
@@ -204,9 +194,8 @@ public class FeedParser {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private String findSelf(SyndFeed feed) {
|
private String findSelf(SyndFeed feed) {
|
||||||
for (SyndLink l : (List<SyndLink>) feed.getLinks()) {
|
for (SyndLink l : feed.getLinks()) {
|
||||||
if ("self".equalsIgnoreCase(l.getRel())) {
|
if ("self".equalsIgnoreCase(l.getRel())) {
|
||||||
log.debug("found self {} for feed {}", l.getHref(), feed.getLink());
|
log.debug("found self {} for feed {}", l.getHref(), feed.getLink());
|
||||||
return l.getHref();
|
return l.getHref();
|
||||||
|
|||||||
@@ -1,38 +1,45 @@
|
|||||||
package com.commafeed.backend.feed;
|
package com.commafeed.backend.feed;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
import org.apache.commons.lang.time.DateUtils;
|
import org.apache.commons.lang3.time.DateUtils;
|
||||||
|
import org.hibernate.SessionFactory;
|
||||||
|
|
||||||
import com.codahale.metrics.Gauge;
|
import com.codahale.metrics.Gauge;
|
||||||
import com.codahale.metrics.Meter;
|
import com.codahale.metrics.Meter;
|
||||||
import com.codahale.metrics.MetricRegistry;
|
import com.codahale.metrics.MetricRegistry;
|
||||||
import com.commafeed.CommaFeedConfiguration;
|
import com.commafeed.CommaFeedConfiguration;
|
||||||
import com.commafeed.backend.dao.FeedDAO;
|
import com.commafeed.backend.dao.FeedDAO;
|
||||||
|
import com.commafeed.backend.dao.UnitOfWork;
|
||||||
import com.commafeed.backend.model.Feed;
|
import com.commafeed.backend.model.Feed;
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import com.google.common.collect.Queues;
|
|
||||||
|
|
||||||
|
@Singleton
|
||||||
public class FeedQueues {
|
public class FeedQueues {
|
||||||
|
|
||||||
|
private SessionFactory sessionFactory;
|
||||||
private final FeedDAO feedDAO;
|
private final FeedDAO feedDAO;
|
||||||
private final CommaFeedConfiguration config;
|
private final CommaFeedConfiguration config;
|
||||||
|
|
||||||
private Queue<FeedRefreshContext> addQueue = Queues.newConcurrentLinkedQueue();
|
private Queue<FeedRefreshContext> addQueue = new ConcurrentLinkedQueue<>();
|
||||||
private Queue<FeedRefreshContext> takeQueue = Queues.newConcurrentLinkedQueue();
|
private Queue<FeedRefreshContext> takeQueue = new ConcurrentLinkedQueue<>();
|
||||||
private Queue<Feed> giveBackQueue = Queues.newConcurrentLinkedQueue();
|
private Queue<Feed> giveBackQueue = new ConcurrentLinkedQueue<>();
|
||||||
|
|
||||||
private Meter refill;
|
private Meter refill;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public FeedQueues(FeedDAO feedDAO, CommaFeedConfiguration config, MetricRegistry metrics) {
|
public FeedQueues(SessionFactory sessionFactory, FeedDAO feedDAO, CommaFeedConfiguration config, MetricRegistry metrics) {
|
||||||
|
this.sessionFactory = sessionFactory;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.feedDAO = feedDAO;
|
this.feedDAO = feedDAO;
|
||||||
|
|
||||||
@@ -76,7 +83,10 @@ public class FeedQueues {
|
|||||||
public void add(Feed feed, boolean urgent) {
|
public void add(Feed feed, boolean urgent) {
|
||||||
int refreshInterval = config.getApplicationSettings().getRefreshIntervalMinutes();
|
int refreshInterval = config.getApplicationSettings().getRefreshIntervalMinutes();
|
||||||
if (feed.getLastUpdated() == null || feed.getLastUpdated().before(DateUtils.addMinutes(new Date(), -1 * refreshInterval))) {
|
if (feed.getLastUpdated() == null || feed.getLastUpdated().before(DateUtils.addMinutes(new Date(), -1 * refreshInterval))) {
|
||||||
addQueue.add(new FeedRefreshContext(feed, urgent));
|
boolean alreadyQueued = addQueue.stream().anyMatch(c -> c.getFeed().getId().equals(feed.getId()));
|
||||||
|
if (!alreadyQueued) {
|
||||||
|
addQueue.add(new FeedRefreshContext(feed, urgent));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +96,7 @@ public class FeedQueues {
|
|||||||
private void refill() {
|
private void refill() {
|
||||||
refill.mark();
|
refill.mark();
|
||||||
|
|
||||||
List<FeedRefreshContext> contexts = Lists.newArrayList();
|
List<FeedRefreshContext> contexts = new ArrayList<>();
|
||||||
int batchSize = Math.min(100, 3 * config.getApplicationSettings().getBackgroundThreads());
|
int batchSize = Math.min(100, 3 * config.getApplicationSettings().getBackgroundThreads());
|
||||||
|
|
||||||
// add feeds we got from the add() method
|
// add feeds we got from the add() method
|
||||||
@@ -98,7 +108,7 @@ public class FeedQueues {
|
|||||||
// add feeds that are up to refresh from the database
|
// add feeds that are up to refresh from the database
|
||||||
int count = batchSize - contexts.size();
|
int count = batchSize - contexts.size();
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
List<Feed> feeds = feedDAO.findNextUpdatable(count, getLastLoginThreshold());
|
List<Feed> feeds = UnitOfWork.call(sessionFactory, () -> feedDAO.findNextUpdatable(count, getLastLoginThreshold()));
|
||||||
for (Feed feed : feeds) {
|
for (Feed feed : feeds) {
|
||||||
contexts.add(new FeedRefreshContext(feed, false));
|
contexts.add(new FeedRefreshContext(feed, false));
|
||||||
}
|
}
|
||||||
@@ -106,7 +116,7 @@ public class FeedQueues {
|
|||||||
|
|
||||||
// set the disabledDate as we use it in feedDAO to decide what to refresh next. We also use a map to remove
|
// set the disabledDate as we use it in feedDAO to decide what to refresh next. We also use a map to remove
|
||||||
// duplicates.
|
// duplicates.
|
||||||
Map<Long, FeedRefreshContext> map = Maps.newLinkedHashMap();
|
Map<Long, FeedRefreshContext> map = new LinkedHashMap<>();
|
||||||
for (FeedRefreshContext context : contexts) {
|
for (FeedRefreshContext context : contexts) {
|
||||||
Feed feed = context.getFeed();
|
Feed feed = context.getFeed();
|
||||||
feed.setDisabledUntil(DateUtils.addMinutes(new Date(), config.getApplicationSettings().getRefreshIntervalMinutes()));
|
feed.setDisabledUntil(DateUtils.addMinutes(new Date(), config.getApplicationSettings().getRefreshIntervalMinutes()));
|
||||||
@@ -124,11 +134,8 @@ public class FeedQueues {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update all feeds in the database
|
// update all feeds in the database
|
||||||
List<Feed> feeds = Lists.newArrayList();
|
List<Feed> feeds = map.values().stream().map(c -> c.getFeed()).collect(Collectors.toList());
|
||||||
for (FeedRefreshContext context : map.values()) {
|
UnitOfWork.run(sessionFactory, () -> feedDAO.saveOrUpdate(feeds));
|
||||||
feeds.add(context.getFeed());
|
|
||||||
}
|
|
||||||
feedDAO.merge(feeds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -143,7 +150,7 @@ public class FeedQueues {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Date getLastLoginThreshold() {
|
private Date getLastLoginThreshold() {
|
||||||
if (config.getApplicationSettings().isHeavyLoad()) {
|
if (config.getApplicationSettings().getHeavyLoad()) {
|
||||||
return DateUtils.addDays(new Date(), -30);
|
return DateUtils.addDays(new Date(), -30);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -2,9 +2,14 @@ package com.commafeed.backend.feed;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
import com.commafeed.backend.model.Feed;
|
import com.commafeed.backend.model.Feed;
|
||||||
import com.commafeed.backend.model.FeedEntry;
|
import com.commafeed.backend.model.FeedEntry;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
public class FeedRefreshContext {
|
public class FeedRefreshContext {
|
||||||
private Feed feed;
|
private Feed feed;
|
||||||
private List<FeedEntry> entries;
|
private List<FeedEntry> entries;
|
||||||
@@ -14,29 +19,4 @@ public class FeedRefreshContext {
|
|||||||
this.feed = feed;
|
this.feed = feed;
|
||||||
this.urgent = isUrgent;
|
this.urgent = isUrgent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Feed getFeed() {
|
|
||||||
return feed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFeed(Feed feed) {
|
|
||||||
this.feed = feed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isUrgent() {
|
|
||||||
return urgent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUrgent(boolean urgent) {
|
|
||||||
this.urgent = urgent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<FeedEntry> getEntries() {
|
|
||||||
return entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEntries(List<FeedEntry> entries) {
|
|
||||||
this.entries = entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ import java.util.concurrent.RejectedExecutionHandler;
|
|||||||
import java.util.concurrent.ThreadPoolExecutor;
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
import com.codahale.metrics.Gauge;
|
import com.codahale.metrics.Gauge;
|
||||||
import com.codahale.metrics.MetricRegistry;
|
import com.codahale.metrics.MetricRegistry;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wraps a {@link ThreadPoolExecutor} instance. Blocks when queue is full instead of rejecting the task. Allow priority queueing by using
|
* Wraps a {@link ThreadPoolExecutor} instance. Blocks when queue is full instead of rejecting the task. Allow priority queueing by using
|
||||||
* {@link Task} instead of {@link Runnable}
|
* {@link Task} instead of {@link Runnable}
|
||||||
@@ -37,7 +37,14 @@ public class FeedRefreshExecutor {
|
|||||||
return offerLast(r);
|
return offerLast(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}) {
|
||||||
|
@Override
|
||||||
|
protected void afterExecute(Runnable r, Throwable t) {
|
||||||
|
if (t != null) {
|
||||||
|
log.error("thread from pool {} threw a runtime exception", poolName, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
pool.setRejectedExecutionHandler(new RejectedExecutionHandler() {
|
pool.setRejectedExecutionHandler(new RejectedExecutionHandler() {
|
||||||
@Override
|
@Override
|
||||||
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
|
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
|
||||||
|
|||||||
@@ -6,25 +6,23 @@ import java.util.concurrent.ExecutorService;
|
|||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.hibernate.SessionFactory;
|
|
||||||
|
|
||||||
import com.codahale.metrics.Meter;
|
import com.codahale.metrics.Meter;
|
||||||
import com.codahale.metrics.MetricRegistry;
|
import com.codahale.metrics.MetricRegistry;
|
||||||
import com.commafeed.CommaFeedConfiguration;
|
import com.commafeed.CommaFeedConfiguration;
|
||||||
import com.commafeed.backend.dao.FeedDAO;
|
import com.commafeed.backend.dao.FeedDAO;
|
||||||
import com.commafeed.backend.dao.UnitOfWork;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Infinite loop fetching feeds from @FeedQueues and queuing them to the {@link FeedRefreshWorker} pool.
|
* Infinite loop fetching feeds from @FeedQueues and queuing them to the {@link FeedRefreshWorker} pool.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@Singleton
|
||||||
public class FeedRefreshTaskGiver implements Managed {
|
public class FeedRefreshTaskGiver implements Managed {
|
||||||
|
|
||||||
private final SessionFactory sessionFactory;
|
|
||||||
private final FeedQueues queues;
|
private final FeedQueues queues;
|
||||||
private final FeedRefreshWorker worker;
|
private final FeedRefreshWorker worker;
|
||||||
|
|
||||||
@@ -34,9 +32,8 @@ public class FeedRefreshTaskGiver implements Managed {
|
|||||||
private Meter threadWaited;
|
private Meter threadWaited;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public FeedRefreshTaskGiver(SessionFactory sessionFactory, FeedQueues queues, FeedDAO feedDAO, FeedRefreshWorker worker,
|
public FeedRefreshTaskGiver(FeedQueues queues, FeedDAO feedDAO, FeedRefreshWorker worker, CommaFeedConfiguration config,
|
||||||
CommaFeedConfiguration config, MetricRegistry metrics) {
|
MetricRegistry metrics) {
|
||||||
this.sessionFactory = sessionFactory;
|
|
||||||
this.queues = queues;
|
this.queues = queues;
|
||||||
this.worker = worker;
|
this.worker = worker;
|
||||||
|
|
||||||
@@ -66,18 +63,11 @@ public class FeedRefreshTaskGiver implements Managed {
|
|||||||
public void run() {
|
public void run() {
|
||||||
while (!executor.isShutdown()) {
|
while (!executor.isShutdown()) {
|
||||||
try {
|
try {
|
||||||
FeedRefreshContext context = new UnitOfWork<FeedRefreshContext>(sessionFactory) {
|
FeedRefreshContext context = queues.take();
|
||||||
@Override
|
if (context != null) {
|
||||||
protected FeedRefreshContext runInSession() throws Exception {
|
feedRefreshed.mark();
|
||||||
FeedRefreshContext context = queues.take();
|
worker.updateFeed(context);
|
||||||
if (context != null) {
|
} else {
|
||||||
feedRefreshed.mark();
|
|
||||||
worker.updateFeed(context);
|
|
||||||
}
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
}.run();
|
|
||||||
if (context == null) {
|
|
||||||
log.debug("nothing to do, sleeping for 15s");
|
log.debug("nothing to do, sleeping for 15s");
|
||||||
threadWaited.mark();
|
threadWaited.mark();
|
||||||
try {
|
try {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user